非常教程

JavaScript参考手册

Operators

Object initializer

可以通过new Object()Object.create()方法,或者使用字面量标记(初始化标记)初始化对象。 一个对象初始化器,由花括号/大括号 ({}) 包含的一个由零个或多个对象属性名和其关联值组成的一个逗号分隔的列表构成。

语法

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 2015 的新标记

请参考兼容性表格获取这些标记的支持信息。在不被支持的环境中,这些标记将造成语法错误。

// Shorthand property names (ES2015)
var a = 'foo', b = 42, c = {};
var o = {a, b, c};

// Shorthand method names (ES2015)
var o = {
  property([parameters]) {}
};

// Computed property names (ES2015)
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 (ES2015)
var o = {a, b, c};

// In other words,
console.log((o.a === {a}.a)); // true

重复属性名

属性使用了同样的名称时,后面的属性会覆盖前面的属性。

var a = {x: 1, x: 2};
console.log(a); // {x: 2}

在 ECMAScript 5 严格模式的代码中, 重复的属性名会被当做SyntaxError。引入计算的属性名以后,属性名会在运行时出现重复。ECMAScript 2015 移除了这个限制。

function haveES2015DuplicatePropertySemantics() {
  '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;
  }
}

方法定义

对象属性也可以是一个函数、getter、setter方法。

var o = {
  property: function ([parameters]) {},
  get property() {},
  set property(value) {}
};

ECMAScript 2015引入了一中简短写法, "function" 关键字也可以丢掉。

// Shorthand method names (ES2015)
var o = {
  property([parameters]) {},
  *generator() {}
};

ECMAScript 2015 提供了一种简明地定义以生成器函数作为值的属性的方法。

var o = {
  *generator() {
    ...........
  }
};

ECMAScript 5 中可以这样书写(需要注意的是 ES5 没有生成器):

var o = {
  generator: function* () {
    ...........
  }
};

获取更多信息和范例,请参考 method definitions。

计算属性名

从ECMAScript 2015开始,对象初始化语法开始支持计算属性名。其允许在[]中放入表达式,计算结果可以当做属性名。这种用法和用方括号访问属性非常类似,也许你已经用来读取和设置属性了。现在同样的语法也可以用于对象字面值了:

// Computed property names (ES2015)
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}

扩展属性

ECMAScript 提案(第3阶段)的剩余/扩展属性将扩展属性添加到对象文字。它将自己提供的对象的枚举属性复制到一个新的对象上。

使用比Object.assign()更短的语法,可以轻松克隆(不包括原型)或合并对象。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

请注意,Object.assign()会触发setter,而展开操作符则不会。

变更原型

定义属性为__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,null或其他(JSON)对象。 
  • JSON中,不允许将值设置为函数。
  • Date 等对象,经JSON.parse()处理后,会变成字符串。
  • JSON.parse() 不会处理计算的属性名,会当做错误抛出。

规范

Specification

Status

Comment

ECMAScript 1st Edition (ECMA-262)

Standard

initial definition.

ECMAScript 5.1 (ECMA-262)The definition of 'Object Initializer' in that specification.

Standard

getter and setter added.

ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Object Initializer' in that specification.

Standard

Shorthand method/property names and computed property names added.

ECMAScript Latest Draft (ECMA-262)The definition of 'Object Initializer' in that specification.

Living Standard

Rest/Spread Properties for ECMAScript

Draft

Stage 3 draft.

浏览器兼容性

Feature

Chrome

Edge

Firefox (Gecko)

Internet Explorer

Opera

Safari

Basic support

1.0

(Yes)

1.0 (1.7 or earlier)

1

1

1

Computed property names

(Yes)

(Yes)

34 (34)

No support

34

7.1

Shorthand property names

(Yes)

(Yes)

33 (33)

No support

34

9

Shorthand method names

42.0

(Yes)

34 (34)

No support

34

9

Spread properties

60

No support

55 (55)

No support

No support

No support

Feature

Android

Android Webview

Edge

Firefox Mobile (Gecko)

IE Mobile

Opera Mobile

Safari Mobile

Chrome for Android

Basic support

(Yes)

(Yes)

(Yes)

1.0 (1.0)

1

1

1

1.0

Computed property names

No support

(Yes)

(Yes)

34.0 (34)

No support

34

7.1

No support

Shorthand property names

No support

(Yes)

(Yes)

33.0 (33)

No support

34

9

No support

Shorthand method names

No support

42.0

(Yes)

34.0 (34)

No support

34

9

42.0

Spread properties

No support

No support

No support

55.0 (55)

No support

No support

No support

No support

JavaScript

JavaScript 是一种高级编程语言,通过解释执行,是一门动态类型,面向对象(基于原型)的解释型语言。它已经由ECMA(欧洲电脑制造商协会)通过 ECMAScript 实现语言的标准化。它被世界上的绝大多数网站所使用,也被世界主流浏览器( Chrome、IE、FireFox、Safari、Opera )支持。JavaScript 是一门基于原型、函数先行的语言,是一门多范式的语言,它支持面向对象编程,命令式编程,以及函数式编程。它提供语法来操控文本、数组、日期以及正则表达式等,不支持 I/O,比如网络