对象可以通过 new Object()
, Object.create() 方法
, 或者使用字面 标记 (初始化 标记)初始化。 对象初始化,由花括号{}包含的一个由0个或者多个对象属性名和关联值组成的列表构成。
语法
var o = {}; var o = { a: "foo", b: 42, c: {} }; var a = "foo", b = 42, c = {}; var o = { a: a, b: b, c: c }; var o = { property: function ([parameters]) {}, get property() {}, set property(value) {}, };
ECMAScript 6新标记
请参考兼容性表格获取这些标记的支持信息。在不被支持的环境中,这些标记将造成语法错误。
// Shorthand property names (ES6) var a = "foo", b = 42, c = {}; var o = { a, b, c }; // Shorthand method names (ES6) var o = { property([parameters]) {}, get property() {}, set property(value) {}, * generator() {} }; // Computed property names (ES6) var prop = "foo"; var o = { [prop]: "hey", ["b" + "ar"]: "there", };
描述
对象初始化是一个描述对象
初始化过程的表达式。对象初始化是由一组描述对象的属性组成。属性的值可以是固有类型,也可以是其他对象。
创建对象
没有属性的空对象可以用以下方式创建:
var object = {};
不过,字面 和初始化 标记的优势在于,可以用内含属性的花括号快速创建对象。简单地编写一个逗号分隔的键:值对的类别。如下代码创建了一个含三个属性的对象,键分别为 "foo", "age" 和 "baz"。这些键对应的值,分别是字符串“bar”,数字42和另一个对象。
var object = { foo: "bar", age: 42, baz: { myProp: 12 }, }
属性访问
创建对象后,可以读取或者修改它。对象属性可以用下标小圆点标记或者方括号标记访问。参考属性访问 获取更多信息。
object.foo; // "bar" object["age"]; // 42 object.foo = "baz";
属性定义
上面学习了如何用初始化标记对象属性。经常能遇到希望将代码中的变量放到对象中的情况。可能遇到如下代码:
var a = "foo", b = 42, c = {}; var o = { a: a, b: b, c: c };
在 ECMAScript 2015中,有更简短的标记可以实现同样的效果:
var a = "foo", b = 42, c = {}; // Shorthand property names (ES6) var o = { a, b, c };
重复属性名
属性使用了同样的名称时,后面的属性会覆盖前面的属性。
var a = {x: 1, x: 2}; console.log(a); // { x: 2}
在 ECMAScript 5 strict 模式的代码中, 重复的属性名会被当做SyntaxError
。引入计算的属性名以后,属性名会在运行时出现重复。ECMAScript 2015 移除了这个限制。
function haveES6DuplicatePropertySemantics(){ "use strict"; try { ({ prop: 1, prop: 2 }); // No error thrown, duplicate property names allowed in strict mode return true; } catch (e) { // Error thrown, duplicates prohibited in strict mode return false; } }
方法定义
var o = { property: function ([parameters]) {}, get property() {}, set property(value) {}, };
ECMAScript 2015引入了一中简短写法, "function" 关键字也可以丢掉。
// Shorthand method names (ES6) var o = { property([parameters]) {}, get property() {}, set property(value) {}, * generator() {} };
ECMAScript 2015 提供了一种简明地定义以生成器函数作为值的属性的方法。
var o = { * generator() { ........... } };
ECMAScript 5 中可以这样书写 (需要注意的时 ES5 没有生成器):
var o = { generatorMethod: function *() { ........... } };
获取更多信息和范例,请参考 method definitions。
计算的属性名
从ECMAScript 2015开始,对象初始化语法开始支持计算的属性名。其允许在[]中放入表达式,计算结果可以当做属性名。这种用法和用方括号访问属性非常类似,也许你已经用来读取和设置属性了。现在同样的语法也可以用于对象字面值了:
// Computed property names (ES6) var i = 0; var a = { ["foo" + ++i]: i, ["foo" + ++i]: i, ["foo" + ++i]: i }; console.log(a.foo1); // 1 console.log(a.foo2); // 2 console.log(a.foo3); // 3 var param = 'size'; var config = { [param]: 12, ["mobile" + param.charAt(0).toUpperCase() + param.slice(1)]: 4 }; console.log(config); // { size: 12, mobileSize: 4 }
变更原型
定义属性为__proto__: 值
或 "__proto__": 值
时,不会创建名为__proto__属性。如果给出的值是对象或者
null
,那么对象的[[Prototype]]会被设置为给出的值。(如果给出的值不是对象也不是null,那么对象的原型不会改变。)
var obj1 = {}; assert(Object.getPrototypeOf(obj1) === Object.prototype); var obj2 = { __proto__: null }; assert(Object.getPrototypeOf(obj2) === null); var protoObj = {}; var obj3 = { "__proto__": protoObj }; assert(Object.getPrototypeOf(obj3) === protoObj); var obj4 = { __proto__: "not an object or null" }; assert(Object.getPrototypeOf(obj4) === Object.prototype); assert(!obj4.hasOwnProperty("__proto__"));
在对象字面值中,仅有一次变更原型的机会;多次变更原型,会被视为语法错误。
不使用冒号标记的属性定义,不会变更对象的原型;而是和其他具有不同名字的属性一样是普通属性定义。
var __proto__ = "variable"; var obj1 = { __proto__ }; assert(Object.getPrototypeOf(obj1) === Object.prototype); assert(obj1.hasOwnProperty("__proto__")); assert(obj1.__proto__ === "variable"); var obj2 = { __proto__() { return "hello"; } }; assert(obj2.__proto__() === "hello"); var obj3 = { ["__prot" + "o__"]: 17 }; assert(obj3.__proto__ === 17);
对象字面值记法和JSON
对象字面值记法和和 JavaScript Object Notation (JSON)是不同的。虽然他们看起来相似,不同点有:
- JSON 只允许
"property": value
syntax形式的属性定义。属性名必须用双引号括起来。且属性定义不允许使用简便写法。 - JSON中,属性的值仅允许字符串,数字,数组,true,false,或者其他JSON对象。
- JSON中,不允许将值设置为函数。
-
Date
等对象,经JSON.parse()
处理后,会变成字符串。 JSON.parse()
不会处理计算的属性名,会当做错误抛出。
规范
规范 | 状态 | 备注 |
---|---|---|
ECMAScript 1st Edition. | Standard | 初始定义 |
ECMAScript 5.1 (ECMA-262) Object Initializer |
Standard | 增加Getter 和 setter |
ECMAScript 2015 (6th Edition, ECMA-262) Object Initializer |
Standard | 增加method/property 简写方法和计算的属性名 |
浏览器兼容性
特性 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support |
1.0 |
1.0 (1.7 or earlier) | 1 | 1 | 1 |
Computed property names | 未实现 | 34 (34) | 未实现 | 未实现 | 7.1.3 |
Shorthand property names | 未实现 | 33 (33) | 未实现 | 未实现 | 未实现 |
Shorthand method names |
42.0 |
34 (34) | 未实现 | 未实现 | 未实现 |
特性 | Android | Android Webview | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|
Basic support |
(Yes) |
(Yes) | 1.0 (1.0) | 1 | 1 | 1 | 1.0 |
Computed property names | 未实现 | (Yes) | 34.0 (34) | 未实现 | 未实现 | 未实现 | 未实现 |
Shorthand property names | 未实现 | (Yes) | 33.0 (33) | 未实现 | 未实现 | 未实现 | 未实现 |
Shorthand method names |
未实现 |
42.0 | 34.0 (34) | 未实现 | 未实现 | 未实现 | 42.0 |