一、对象字面量语法的扩展
1、属性初始化器的简写
ES6中函数的属性名和参数名相同时,可以省略属性名后面的冒号和值。
因为当对象字面量中的属性只有名称时,JS 引擎会在周边作用域查找同名变量。
//ES5及更早版本 function createPerson1(name, age){ return{ name: name, age: age }; } var person1 = createPerson1('张三', 20); console.log(person1.name, person1.age);//张三 20 //ES6版本 function createPerson2(name, age){ return{ name, age }; } var person2 = createPerson2('李四', 21); console.log(person2.name, person2.age);//李四 21
2、方法简写
ES6对象字面量中方法名后面的冒号和function关键字可以省略。
//ES5及更早版本 var person1 = { name: "张三", sayName: function() { console.log(this.name); } }; person1.sayName();//张三 //ES6版本 var person2 = { name: "李四", sayName() { console.log(this.name); } }; person2.sayName();//李四
3、需计算属性名
需计算属性名是对象字面量语法的一部分,用方括号表示法
var suffix = " name"; var person = { ["first" + suffix]: "Nicholas", ["last" + suffix]: "Zakas", age: 20 }; //属性名包含空格,无法用小数点表示法来引用 console.log(person["first name"]); // "Nicholas" console.log(person["last name"]); // "Zakas" console.log(person["age"]);//20 console.log(person.age);//20
二、新的方法
1、Object.is() 方法
比较两个值时,有相等运算符( == )和严格相等运算符( ===)。为了避免在比较时发生强制类型转换,一般使用后者。
但严格相等运算符也并不完全准确,例如,它认为 +0 与 -0 相等,即使这两者在 JS 引擎中有不同的表示;另外 NaN === NaN 会返回 false,因此有必要使用 isNaN() 函数来正确检测 NaN。
ES6引入的Object.is()方法要求二者类型相同并且值也相等。在许多情况下,Object.is() 的结果与 === 算符是相同的,仅有的例外是:
+0 与 -0 不相等,NaN 等于 NaN。
console.log(+0 == -0); // true console.log(+0 === -0); // true console.log(Object.is(+0, -0)); // false console.log(NaN == NaN); // false console.log(NaN === NaN); // false console.log(Object.is(NaN, NaN)); // true console.log(5 == 5); // true console.log(5 == "5"); // true console.log(5 === 5); // true console.log(5 === "5"); // false console.log(Object.is(5, 5)); // true console.log(Object.is(5, "5")); // false
2、Object.assign() 方法
混入( Mixin )模式是指在一次混入中,一个对象会从另一个对象中接收属性与方法。
function mixin(receiver, supplier) { Object.keys(supplier).forEach(function(key) { receiver[key] = supplier[key]; }); return receiver; } function EventTarget() { /*...*/ } EventTarget.prototype = { constructor: EventTarget, emit: function() { /*...*/ }, on: function() { /*...*/ } }; var myObject = {}; mixin(myObject, EventTarget.prototype); myObject.emit("somethingChanged");
mixin() 函数在 supplier 对象的自有属性上进行迭代,并将这些属性复制到 receiver 对象(浅复制,当属性值为对象时,仅复制其引用)。这样 receiver 对象就能获得新的属性而无须使用继承。
myObject 对象接收了 EventTarget.prototype 对象的行为,这给了它分别使用 emit()与 on() 方法来发布事件与订阅事件的能力。
ES6的 Object.assign() 方法来完成同样的行为。
上面代码可以改为
Object.assign(myObject, EventTarget.prototype);
三、重复的对象字面量属性
当存在重复属性时,ES5 严格模式下会报语法错误,但ES6 中排在后面的属性的值会成为该属性的实际值。
"use strict"; var person = { name: "Nicholas", name: "Greg" // 在 ES6 严格模式中不会出错 }; console.log(person.name);//Greg
四、自有属性的枚举顺序
ES5 没有定义对象属性的枚举顺序,而是把该问题留给了 JS 引擎厂商。
ES6 定义了对象自有属性在被枚举时返回的顺序。影响了Object.getOwnPropertyNames()与Reflect.ownKeys的返回属性,还同样影响了Object.assign() 处理属性的顺序。
自有属性枚举时基本顺序如下:
1. 所有的数字类型键,按升序排列。
2. 所有的字符串类型键,按被添加到对象的顺序排列。
3. 所有的符号类型键,也按添加顺序排列。
var obj = { a: 1, 0: 1, c: 1, 2: 1, b: 1, 1: 1 }; obj.d = 1; console.log(Object.getOwnPropertyNames(obj).join("")); // "012acbd"
五、更强大的原型
1、修改对象的原型
ES5,对象的原型在初始化完成后会保持不变。
ES6 通过添加 Object.setPrototypeOf() 方法,允许修改任意指定对象的原型。
let person = { getGreeting() { return "Hello"; } }; let dog = { getGreeting() { return "Woof"; } }; // 原型为 person let friend = Object.create(person); console.log(friend.getGreeting()); // "Hello" console.log(Object.getPrototypeOf(friend) === person); // true // 将原型设置为 dog Object.setPrototypeOf(friend, dog); console.log(friend.getGreeting()); // "Woof" console.log(Object.getPrototypeOf(friend) === dog); // true
2、使用 super 引用的简单原型访问
let person = { getGreeting() { return "Hello"; } }; let dog = { getGreeting() { return "Woof"; } }; let friend = { getGreeting() { //旧的用法 //return Object.getPrototypeOf(this).getGreeting.call(this) + ", hi!"; //新的用法 return super.getGreeting() + ", hi!"; } }; // 将原型设置为 person Object.setPrototypeOf(friend, person); console.log(friend.getGreeting()); // "Hello, hi!" console.log(Object.getPrototypeOf(friend) === person); // true // 将原型设置为 dog Object.setPrototypeOf(friend, dog); console.log(friend.getGreeting()); // "Woof, hi!" console.log(Object.getPrototypeOf(friend) === dog); // true