对象字面量语法扩展
属性初始值的简写
es6之前,如果想为对象字面量添加与作用域中变量同名的属性:
function createPerson(name,age){
return {
name:name,
age:age
}
}
es6中,当一个对象的属性与本地变量同名时,不必再写冒号和值,简单地只写属性名即可:
function createPerson(name,age){
return {
name,
age
}
}
理解:当对象字面量里只有一个属性的名称时,js引擎会在可访问作用域中查找其同名变量;如果找到,改变量的值被赋给对象字面量里的同名属性。
对象方法的简写
es6之前:
let person = {
name:'frontend',
sayName:function(){
console.log(this.name);
}
}
es6:
let person = {
name:'frontend',
sayName(){
console.log(this.name);
}
}
二者唯一区别:简写方法中可以使用super关键字
可计算属性名
属性名用一对[ ] 括起来,主要用于属性名需要计算得出,属性名是变量,属性名中有特殊字符(如" ","."等)
let suffix = 'name';
let person = {
['first' + suffix]:'michael',
['last' + suffix]:'jordan'
}
新增方法
Object.is()方法
js中比较两个值是否相当,通常习惯使用'=='或'==='(区别在于===不会进行强制类型转换),但是通过等号运算符总有一些情况判断不准确,请看:
console.log(+0 == -0); //true
console.log(+0 === -0); //true
console.log(NaN == NaN); //false
console.log(NaN === NaN); //false
Object.is()方法接受两个参数,如果这两个参数类型相同且具有相同的值,则返回true
console.log(Object.is(+0,-0)); //false
console.log(Object.is(NaN,NaN)); //true
Object.is()方法运行结果在大部分情况中与 === 运算符相同,唯一的区别在于+0和-0被识别为相等,NaN和NaN被识别为相等。
Object.assign()方法
mixin是js中实现对象组合最流行的一种模式。es6之前的实现方式:
function mixin(receiver,supplier){
Object.keys(supplier).forEach(function(key){
receiver[key] = supplier[key];
});
return receiver;
}
因为这种混合在各大类库都有实现,于是es6新添加了Object.assign()方法来标准化的实现相同功能。该方法接受一个接收对象和任意数量的源对象,最终返回接收对象。
tips:如果多个源对象具有同名属性,则排位靠后的源对象会覆盖排位靠前的
let receiver={};
Object.assign(receiver,{
type:'js',
name:'index.js'
},{
type:'css'
});
console.log(receiver.type); //css
console.log(receiver.name); //index.js
增强对象原型
改变对象的原型
正常情况下,无论是通过构造函数还是Object.create()创建的对象,其原型是在对象被创建时指定的。
es6添加了Object.setPrototypeOf()方法,该方法可以改变任意指定对象的原型,它接受两个参数:被改变原型的对象和替代第一个参数原型的对象。
let person = {
getGreeting(){
return 'Hello';
}
};
let dog = {
getGreeting(){
return 'Wow';
}
};
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()); //wow
console.log(Object.getPrototypeOf(friend) === dog); //true
对象原型的真实值被存储在内部专用属性[[Prototype]]中,调用Object.getPrototypeOf()返回存储在其中的值,调用Object.setPrototypeOf(),改变其中的值。
super
假设现在需要你重写某个对象实例的方法,又需要调用与它同名的原型方法。你的实现可能如下:
let person = {
getGreeting(){
return 'Hello'
}
}
let dog = {
getGreeting(){
return 'Wow'
}
};
let friend = {
getGreeting(){
return Object.getPrototypeOf(this).getGreeting.call(this) + ', hi !';
}
}
Object.setPrototypeOf(friend,person);
console.log(friend.getGreeting()); //'Hello, hi !'
console.log(Object.getPrototypeOf(friend) === person); //true
Object.setPrototypeOf(friend,dog);
console.log(friend.getGreeting()); //Wow, hi !
console.log(Object.getPrototypeOf(friend) === dog); //true
乍一看上面的代码是可以满足我们预期的,但是如果你的代码中出现了多重继承,情况可就有些糟糕了:
let person = {
getGreeting(){
return 'Hello'
}
}
let friend = {
getGreeting(){
return Object.getPrototypeOf(this).getGreeting.call(this) + ', hi!';
}
}
Object.setPrototypeOf(friend,person);
let relative = Object.create(friend);
console.log(person.getGreeting()); //'Hello'
console.log(friend.getGreeting()); //'Hello, hi!'
console.log(relative.getGreeting()); //报错
让我们来分析一下报错的那条语句的执行过程:
relative调用getGreeting方法,然而relative这个对象并没有这个方法,所以沿着原型链搜索到了friend对象,这里有getGreeting方法,然后开始这行friend对象上的getGreeting方法,注意,此时的调用者是relative对象,所以this是指向relative的,进入getGreeting方法执行语句,遇到Object.getPrototypeOf(this),此时this指向relative,也就相当于执行了Object.getPrototypeOf(relative),relative的原型是friend,所以又找到了friend....
有点眼熟了吧,仿佛是个无限递归哦,所以就出了上图中栈溢出的错误!
es6中引入了super关键字,super引用相当于指向对象原型的指针,即Object.getPrototypeOf(this)的值。super引用不是动态变化的,它总是指向正确的对象,所以,将 Object.getPrototypeOf(this)替换为super,问题即可迎刃而解。
tips:使用super关键字需要在使用简写方法的对象中,如果在其它方法声明中使用会导致语法错误。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。