1 概述
1.1 结构
对象是一组无序键值对,是 JavaScript 最重要的数据类型。
var obj = {
foo: 'Hello',
bar: 'World'
};
所有键都是字符串( ES6 引入的 Symbol 值也可以作为键),非字符串键会自动向字符串转换。特别注意数值键的转换方式。键又称属性。属性之间用逗号分隔,末端逗号可加可不加。
var obj = {
1: 'a',
3.2: 'b',
1e2: true,
1e-2: true,
.234: true,
0xFF: true
};
obj
// Object {
// 1: "a",
// 3.2: "b",
// 100: true,
// 0.01: true,
// 0.234: true,
// 255: true
// }
obj['100'] // true
值可以是任何数据类型。函数类型的值称为方法。如果属性的值还是一个对象,就形成了链式引用。
var obj = {
p: function (x) {
return 2 * x;
}
};
obj.p(1) // 2
1.2 引用
如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
此时如果取消某一个变量对于原对象的引用,不会影响到另一个变量。但是这种引用只局限于对象,指向原始类型的变量复制的是值。
var o1 = {};
var o2 = o1;
o1 = 1;
o2 // {}
var x = 1;
var y = x;
x = 2;
y // 1
1.3 是对象还是区块
对象也采用大括号表示,如果行首是一个大括号,它到底是对象还是区块?
{ foo: 123 }
- 一个包含
foo
属性的对象 - 一个包含
foo
标签的区块
JavaScript 引擎的做法是一律解释为区块。如果想要声明对象,请在大括号外加上圆括号,因为圆括号的里只能是表达式,确保了大括号只能解释为对象。在对字符串求值的 eval
语句中反映得最明显。
({ foo: 123 }) // 正确
({ console.log(123) }) // 报错
eval('{foo: 123}') // 123
eval('({foo: 123})') // {foo: 123}
2 属性
2.1 赋值
属性支持动态创建,不一定要在对象声明时就指定。
var obj = { p: 1 };
// 等价于
var obj = {};
obj.p = 1;
2.2 查看
查看一个对象本身的所有属性,可以使用 Object.keys
方法。
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj); // ['key1', 'key2']
in
用于检查对象是否包含某个属性。它不能识别哪些是自身的,哪些是继承的,这得使用 hasOwnProperty()
方法来判断。
var obj = {};
if ('toString' in obj) {
console.log(obj.hasOwnProperty('toString')) // false
}
for...in
用来遍历一个对象的全部可遍历属性,不可遍历属性会被跳过。举例来说,对象都继承了 toString
属性,但是 for...in
不会遍历到它。
2.3 读取
var foo = 'bar';
var obj = {
foo: 1,
bar: 2
};
obj.foo // 1
obj.['foo'] // 1
obj[foo] // 2
若使用方括号读取,键必须有引号,否则被当作变量处理。方括号内支持表达式。数值键可以不加引号,会自动转成字符串。数值键不能使用点运算符(会被当成小数点),只能使用方括号。
var obj = {
123: 'hello world'
};
obj.123 // 报错
obj[123] // "hello world"
2.4 删除
var obj = { p: 1 };
Object.keys(obj) // ["p"]
delete obj.p // true
obj.p // undefined
Object.keys(obj) // []
注意,删除一个不存在的属性不会报错且返回 true
。只有一种情况会返回 false
,那就是该属性存在且禁止删除。
var obj = Object.defineProperty({}, 'p', {
value: 123,
configurable: false
});
obj.p // 123
delete obj.p // false
3 with
with
语句的作用是方便书写。
// 例一
var obj = {
p1: 1,
p2: 2,
};
with (obj) {
p1 = 4;
p2 = 5;
}
// 等同于
obj.p1 = 4;
obj.p2 = 5;
// 例二
with (document.links[0]) {
console.log(href);
console.log(title);
console.log(style);
}
// 等同于
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);
注意,若 with
区块内部有赋值操作,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量,因为 with
区块没有改变作用域。
var obj = {};
with (obj) {
p1 = 4;
p2 = 5;
}
obj.p1 // undefined
p1 // 4
建议不使用 with
语句,用一个临时变量代替。
with (obj1.obj2.obj3) {
console.log(p1 + p2);
}
// 写成
var temp = obj1.obj2.obj3;
console.log(temp.p1 + temp.p2);