对象 (object)

一个对象就是一系列属性的集合,一个属性包含一个名和一个值

例:

1
2
3
4
5
6
7
8
9
10
/* 对象字面量 */
{
name: 'zs',
age: 18,
sex: true,
sayHi: {
first: 'Bob',
last: 'Smith'
}
}

对象是由一系列属性组成,每一个属性都有一个名字(如上面案例中的 name、age),和一个值(如上面案例中的 ‘zs’、18)。每一个名/值对之间用逗号( , )分隔,并且名和值之间由冒号( : )分隔

对象中的属性值可以是任何类型的数据( 包括对象 )

创建对象

使用 对象字面量 创建一个对象

语法:

1
var 对象名 = 对象字面量

例:

1
2
3
4
5
6
7
var obj = {}	//创建一个名为obj的对象
console.log(typeof obj); // 'object'
/* 创建一个名为obj2的对象,对象中包含两个属性 */
var obj2 = {
name: 'Tom',
age: 18
}

访问对象表达式

1、点表示法

语法:

1
对象.属性名

例:

1
2
3
person;					//返回person对象
person.name; //返回person对象中name属性的值
person.age = 18; //向person对象中的name属性赋值

2、括号表示法

语法:

1
对象[属性名]

属性与变量

对象中的属性和变量都可以用来存储任意类型的数据,并且它们的值都是可以更变的

  • 当向对象中的属性赋值时,如果对象中不包含该属性,则会自动添加该属性并赋值

点与括号

点和括号都可以用来分隔对象的名称字段,在对象中,属性名可以是任何字符

  • 点表示法只能使用合法字符作为属性名,而括号表示法可以将任何表达式的值作为属性名
  • 如果属性名为不合法( 与 Js 语法相冲突 )的标识符,则必须用括号表示法

例:

1
2
3
4
5
6
7
8
9
10
/* 例1 */
var obj = {
['.+-*/&|!']: 1234
}
console.log(obj['.+-*/&|!']) //返回1234
/* 例2 */
var o1 = 'name';
var obj2 = {
[o1]: 'Joy' //将变量o1的值作为属性名
}

在实际开发中对象的属性名尽量按照标识符的规范命名

delete 运算符

当要删除一个对象中的属性时,可以使用 delete 运算符

语法:

1
2
3
delete 对象.属性名
or
delete 对象[属性名]

例:

1
2
3
4
5
var obj = {
one: 1
}
delete obj.one;
console.log(obj); //输出为 {} 空对象

数组(array)

数组是一个有序的数据集合,通常被描述为“像列表一样的对象”

例:

1
2
3
4
5
6
7
8
/* 数组字面量 */
[
0,
true,
'hello',
[1,2,3],
{name: 'Joy'}
]

数组由一系列的值组成,每一个值被称作一个元素( 元素可以是任何类型的数据,包括对象 ),且值与值之间用( , )分隔

创建数组

语法:

1
var 数组名 = 数组字面量

例:

1
2
3
var arr = [];	//创建一个名为arr的数组
/* 创建一个名为arr2的数组,数组中包含3个元素 */
var arr2 = [ 1, 2, 3 ];

访问数组表达式

语法:

1
数组[索引]

例:

1
2
3
list			//返回list数组
list[0]; //返回list数组中第1个元素的值
list[0] = 1;//向list数组中的第1个元素赋值

索引

数组中每一个元素都有一个数字编号称为索引,索引是从0开始的整数,通过索引可以访问数组元素的值

数组也是对象

数组用[]表示,对象用{}表示。数组和对象一样,都可以添加属性,区别是数组中如果属性名为整数字符,则会将其作为数组元素( 有序数据 )来表示

使用 typeof 检查数组数据类型时,返回 ‘object’

1
2
var arr = [];
typeof arr // 'object'

数组的实例属性和方法

属性:

  • .length 返回或更改数组的长度

方法:

方法描述原数组
.concat()将两个或多个数组连接合并为一个数组,并返回合并后的数组不改变
.join()将一个数组的所有元素连接成一个字符串,并返回这个字符串不改变
.pop()删除并返回数组中最后一个元素改变
.shift()删除并返回数组中的第一个元素改变
.push()将一个或多个元素添加到数组的末尾,并返回该数组的新长度(.length)改变
.unshift()将一个或多个元素添加到数组的开头,并返回该数组的新长度(.length)改变
.sort()对数组的元素进行排序,并返回排列后的数组改变
.reverse()颠倒数组中元素的顺序,并返回颠倒后的数组改变
.slice()提取数组中指定的元素,并将提取出的元素作为新的数组返回不改变
.splice()删除或替换数组中指定的元素,并将删除或替换后的数组返回改变
.indexOf()查找数组中是否包含指定的元素,如果不包含则返回-1,包含则返回该元素的索引值不改变

in 运算符

in运算符可以检测一个属性是否在指定的对象中,如果在则返回 true,不在则返回 false

语法:

1
属性 in 对象名 //属性可以是属性名( 字符串 ) 或 数组索引( 数字 )

例:

1
2
3
4
5
6
var obj = {
a: 1,
b: 2,
c: 3
}
console.log('a' in obj, 'x' in obj); //输出:true false

for…in

for...in语句用来迭代对象中所有可枚举的属性

语法:

1
2
3
for (变量 in 对象名) {
//循环体(语句)
}

例:

1
2
3
4
var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}

PS:当 in运算符在 for语句中使用时,其作用就会增加( 增加了赋值和迭代的作用 )

执行步骤:

for...in 语句中,in运算符会先将对象中的第1个属性名赋值到左侧变量中,赋值完成后就会执行一次循环体,之后跳回赋值阶段赋值第2个属性名,并再次执行循环体,以此不断循环直至循环到最后一个属性名为止

原始值和引用值

JavaScript 基本数据类型在语言最底层面表现为不可变值,这些值被称为原始值,如:数值,布尔值等…

JavaScript 中 像对象、数组和函数都被称为引用值,它在语言最底层面表现为可变值

这里的可变值是指无需创建新值即可更改的值,而不可变值是指如果不创建新的值,就无法更改其数据的值

ECMAScript 标准中指定原始值存储在栈内存中,而引用值存储在堆内存中。栈内存和堆内存代表了 2 种不同的存储方式

栈内存( stack memory )

  • 栈内存是一个连续的内存空间,栈内存遵循 FILO 的原则,即 后进先出 的原则
  • 栈内存用来存储大小固定的数据,这些数据在编译时大小就被确定
  • 在 JavaScript 中,栈内存主要被用来存储函数执行上下文及其变量
  • 栈内存的数据存取速度要高于堆内存

堆内存( heap memory )

  • 堆内存是一种非连续的存储结构,通常采用链表或树形结构进行管理
  • 堆内存中每个数据项都保存了指向其它数据项的地址信息,这使得堆内存的存取非常灵活
  • 堆内存空间是在运行时动态分配的,用于存储一些大小不确定的数据
  • 当堆内存中的某个数据不再被引用时,它所占用的内存会被 JavaScript 引擎中的垃圾回收器自动释放。垃圾回收器会根据一定的算法来判断哪些数据没有被引用,然后释放这些数据所占用的内存

例:

1
2
3
var a = 123;
var b = a;
a = 456;

例图:

img01

当创建一个对象时,会先在堆内存中分配一块内存空间来存储对象,而栈内存则存储的是该对象所在堆内存的内存地址(引用值)

例图:

img02

例:

1
2
3
4
5
6
7
var obj1 = {
name: '张三'
}
var obj2 = obj1;
obj2.name = "李四";
console.log(obj1.name); //输出:'李四'
console.log(obj2.name); //输出:'李四'