- 简单来说,对象就是一组“键值对”(key-value)的集合
var obj = {
foo: 'Hello',
bar: 'World'
};
上面代码中,大括号就定义了一个对象,它被赋值给变量obj
,所以变量obj
就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: 'Hello'
,其中foo
是“键名”(成员的名称),字符串Hello
是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: 'World'
,bar
是键名,World
是键值。两个键值对之间用逗号分隔。
- 值得注意的是,对象的所有键名都是字符串,加不加引号都可以。若键名是数值,也会被自动转化为字符串
var obj = {
1: 'a',
3.2: 'b',
1e2: true,
1e-2: true,
.234: true,
0xFF: true
};
但是,若键名不符合标识名的条件,且不是数字,则必须加上引号,否则会报错
var obj = {
'1p': 'Hello World',
'h w': 'Hello World',
'p+q': 'Hello World'
};
- 键名又称为属性,其键值可以为数据类型。
(1)若键值为函数,则把此属性称为方法
(2)若键值仍为对象,则构成链式引用
(3)对象的属性间用逗号分隔,最后一个属性可加可不加,最好还是加上
对象和变量引用上的区别
变量名引用对象时,是将多个名字指向了同一个地址。修改一个变量,会影响所有变量
var o1 = {};
var o2 = o1;
o1.a = 1;
o2.a // 1
o2.b = 2;
o1.b // 2
但是多个变量指向一个原始类型的值时,实际上是值的拷贝。修改一个变量,另一个变量不变化
var x = 1;
var y = x;
x = 2;
y // 1
js引擎如何理解对象的大括号
- 对象采用大括号表示,当js读到大括号时,怎么理解代码呢?
{ foo: 123 }
本来,大括号可能有两种含义。可能是表达式,表示一个包含foo属性的对象;也可能是代码区块,里边有标签指向表达式123
为了避免这种歧义,js引擎在遇到这种情况时,一律解释为代码块。因为这种代码,只有解释为代码块才能执行
{ console.log(123) } // 123
- 所以,若果我们想要引擎把大括号解释为对象,最好在大括号前加上圆括号。因为圆括号的里面,只能是表达式,所以确保大括号只能解释为对象。
这种差异在eval
语句(作用是对字符串求值)中反映得最明显。
eval('{foo: 123}'
) // 123
eval('({foo: 123})') // {foo: 123}
没有圆括号,理解为代码块;有圆括号,理解为对象
属性的操作
读取:可以使用点运算符或者方括号运算符
- 值得注意的是,若使用方括号运算符,键名必须放到引号里边,否则会被当成变量处理
var foo = 'bar';
var obj = {
foo: 1,
bar: 2
};
obj.['foo']//1
obj.foo // 1
obj[foo] // 2
- 方括号内部可以使用表达式
obj['hello' + ' world']
obj[3 + 3]
- 当键名是数字时,可以不加引号,因为会自动转化为字符串。但是数值键名不能使用点运算符(会被当成小数点),只能使用方括号运算符
var obj = {
123: 'hello world'
};
obj.123 // 报错
obj[123] // "hello world"
其他属性方法
- 赋值:js允许属性的后绑定,即可以在任何时刻新增属性,而没必要在定义对象的时候,就定义好属性。
- 查看:可以使用
Object.keys
方法,查看一个对象的所有属性
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
- 删除:
delete
命令用于删除对象的属性,删除成功后返回true
。值得注意的是,当删除一个不存在的属性时,delect不会报错,而且返回true;只有当该属性存在且不得删除时,才会返回false;另外,delete命令只能删除对象本身的属性,无法删除继承的属性
var obj = Object.defineProperty({}, 'p', {
value: 123,
configurable: false
});
obj.p // 123
delete obj.p // false
var obj = {};
delete obj.toString // true
obj.toString // function toString() { [native code] }
上面代码中,toString
是对象obj
继承的属性,虽然delete
命令返回true
,但该属性并没有被删除,依然存在。这个例子还说明,即使delete
返回true
,该属性依然可能读取到值。
- 属性是否存在:
in
运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true
,否则返回false
。它的左边是一个字符串,表示属性名,右边是一个对象。
var obj = { p: 1 };
'p' in obj // true
'toString' in obj // true
值得注意的是,in不能识别哪些属性是对象自身的,哪些属性是继承的。我们可以使用对象的hasOwnProperty
方法判断一下,是否为对象自身的属性。
var obj = {};
if ('toString' in obj) {
console.log(obj.hasOwnProperty('toString')) // false
}
- 遍历:
for...in
循环用来遍历一个对象的全部属性。
var obj = {a: 1, b: 2, c: 3};
for (var i in obj) {
console.log('键名:', i);
console.log('键值:', obj[i]);
}
值得注意的是,for...in不仅遍历对象自身的属性,还会遍历继承的属性;但是另一方面,for...in遍历的是对象所有的可遍历属性,会跳过不可遍历的属性。这就解释了为何对象都继承了toString
属性,但是for...in
循环不会遍历到这个属性。
因为toString虽然是继承来的,但是属于不可遍历的,所以不被遍历。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。