ES6 通过字面量语法扩展、新增方法、改进原型等多种方式加强对象的使用,并通过解构简化对象的数据提取过程。
一、字面量语法扩展
在 ES6 模式下使用字面量创建对象更加简洁,对于对象属性来说,属性初始值可以简写,并可以使用可计算的属性名称。对象方法的定义消除了冒号和 function 关键字,示例如下:
// Demo1 var value = "name", age = 18 var person = { age, // age: age ['my' + value]: 'Jenny', // myname sayName () { // sayName: function() console.log(this.myname) } } console.log(person.age) // 18 console.log(person.myname) // Jenny person.sayName(); // Jenny
针对重复定义的对象字面量属性,ES5严格模式下会进行重复属性检查从而抛出错误,而ES6移除了这个机制,无论严格模式还是非严格模式,同名属性都会取最后一个值。
// demo2 var person = { ['my' + value]: 'Jenny', myname: 'Tom', myname: 'Lee', } console.log(person.myname) // Lee
二、新增方法
从 ES5 开始遵循的一个设计目标是,避免创建新的全局函数,也不在object.prototype上创建新的方法。
为了是某些任务更容易实现,ES6 在全局 Object 对象上引入一些新的方法。
2.1 Object.is( )
ES6 引入Object.is()方法来弥补全等运算符的不准确计算。
全等运算符在比较时不会触发强制转换类型,Object.is()运行结果也类似,但对于 +0 和 -0(在 JS 引擎中为两个不同实体)以及特殊值NaN的比较结果不同,示例来看:
// demo3 console.log(5 == '5') // true console.log(5 === '5') // false console.log(Object.is(5, '5')) // false 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
总结来说,Object.is()对所有值进行了更严格等价判断。当然,是否使用Object.is()代替全等操作符(===)取决于这些特殊情况是否影响代码。
2.2 Object.assign( )
ES6 添加Object.assign()来实现混合(Mixin)模式,即一个对象接收另一个对象的属性和方法。注意是接收而不是继承,例如接收 demo1 中的对象:
// demo4 var friend = {} Object.assign(friend, person) friend.sayName() // Jenny console.log(friend.age) // 18 console.log(Object.getPrototypeOf(friend) === person) // false
在Object.assign()之前,许多 JS 库自定义了混合方法 mixin( ) 来实现对象组合,代码类似于:
function mixin(receiver, supplier) { Object.keys(supplier).forEach(function (key) { receiver[key] = supplier[key] }) return receiver }
可以看出 mixin( ) 方法使用“=”赋值操作,并不能复制访问器属性,同理Object.assign()也不能复制访问器属性,只是执行了赋值操作,访问器属性最终会转变为接收对象的数据属性。示例如下:
// demo5 var animal = { name: 'lili', get type () { return this.name + type }, set type (news) { type = news } } animal.type = 'cat' console.log(animal.type) // lilicat var pet = {} Object.assign(pet, animal) console.log(animal) // { name: 'lili', type: [Getter/Setter] } console.log(pet) // { name: 'lili', type: 'lilicat' }
2.3 Object.setPrototypeOf( )
正常情况下对通过构造函数或Object.create()创建时,原型是被指定的。ES6 添加Object.setPrototypeOf() 方法来改变对象的原型。
例如创建一个继承 person 对象的 coder 对象,然后改变 coder 对象的原型:
// demo6 let person = { myname: 'Jenny', sayName () { console.log(this.myname) } } // 创建原型为 person 的 coder 对象 let coder = Object.create(person) coder.sayName() // Jenny console.log(Object.getPrototypeOf(coder) === person) // true let hero = { myname: 'lee', sayName () { console.log(this.myname) } } // 改变 coder 对象的原型为 hero Object.setPrototypeOf(coder, hero) coder.sayName() // lee console.log(Object.getPrototypeOf(coder) === hero) // true
对象原型被存储在内部专有属性[[Prototype]],调用Object.getPrototypeOf()返回存储在其中的值,调用Object.setPrototypeOf()改变其值。这个方法加强了对对象原型的操作,下一节重点讲解其它操作原型的方式。
三、增强对象原型
原型是 JS 继承的基础,ES6 针对原型做了很多改进,目的是更灵活地方式使用原型。除了新增的Object.setPrototypeOf()改变原型外,还引入Super关键字简化对原型的访问,
3.1 Super关键字
ES6 引入Super来更便捷的访问对象原型,上一节介绍 ES5 可以使用Object.getPrototypeOf()返回对象原型。举例说明Super的便捷,当对象需要复用原型方法,重新定义自己的方法时,两种实现方式如下: