ECMAScript.6 对象相关
对象字面量
function createPerson(name,age){
return {
name:name,
age:age
}
}
上述代码 createPerson函数返回一个属性名与当前函数参数名相同的对象,如果使用es6语法书写起来会更加简单。
function createPerson(name,age){
return {
name,
age
}
}
简化对象方法
// es5
var person = {
name:"Nicholas",
sayName:function(){
console.log(this.name);
}
}
// es6
var person = {
name:'Nicholas',
sayName(){
console.log(this.name);
}
}
上述两种定义对象方法的区别是 第二种方法可以使用 super。
计算属性
es6之前我们可以在对象的实例上使用 ‘[]’的方式代替 ‘.’设置与获取属性,’[]’内允许使用变量 及进行一些相关的计算, 计算后的结果(String)作为对象的属性使用,但声明对象字面量时则无法使用’[]’,es6增加了对此功能的支持。
// es6前
var a = {};
var num = 1;
a['b' + num] = '2';
a['a b']= '3';
console.log(a.b1);
console.log(a['b' + num]);
console.log(a['a b']);
// throw error
var b = {
['a' + '2']:'3'
}
console.log(b.a2);
// es6
// 对象字面量[] 内 使用变量作为属性名
var lastName = 'last name';
let person = {
'first name':'Nicholas',
[lastName]:'Zakas'
}
console.log(person['first name']); // 'Nicholas'
console.log(person['last name']); // 'Zakas'
console.log(person[lastName]); // 'Zakas'
// [] 内可以进行计算
var suffix = ' name';
var person = {
['first' + suffix] : 'Nicholas',
['last' + suffix] : 'Zakas'
}
console.log(person['first name']); // 'Nicholas'
console.log(person['last name']); // 'Zakas'
属性的遍历顺序
- for...in 只遍历对象自身和继承的可枚举属性(包含继承,不包含Symbol)。
- Object.keys(obj) 返回对象自身的所有可枚举属性的键名(不包含Symbol)
- Object.getOwnPropertyNames(obj) 返回一个数组,包含对象自身的所有属性(但是包括不可枚举属性,不包含Symbol)。
以上方法返回的属性次序规则:
- 遍历所有属性名为数值的属性,按照数字排序
- 遍历所有属性名为字符串的属性,按照生成时间排序
- 遍历所有属性名为Symbol值的属性,按照生成时间排序(Symbol)
var obj = {
a: 1,
0: 1,
d: 1,
2: 1,
b: 1,
1: 1
};
console.log(Object.getOwnPropertyNames(obj).join("")); // "012adb"
obj.c = 1;
console.log(Object.getOwnPropertyNames(obj).join("")); // "012adbc"
Object.is()
Object.is() 与 === 很相似,不同之处在于 +0 与 -0 的比较 、两个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"); // false
console.log(Object.is(5,"5")); //false
Object.assign()
将源对象( source1,source2 )的所有可枚举属性,复制到目标对象(target)
Object.assgin(target,source1,source2)
var receiver = {};
Object.assign(receiver,
{type:'js',name:'file.js'},
{type:'css'}
)
console.log(receiver.type); // "css"
console.log(receiver.name); // "name"
如果使用Object.assgin 复制带有访问器属性的对象时,复制后的属性不是访问器属性而是数据属性。ps:Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
var recevier = {},
supplier = {
get name(){
return 'file.js'
}
};
var descriptor1 = Object.getOwnPropertyDescriptor(supplier,'name');
console.log(descriptor1.value); //undefined
console.log(descriptor1.get); // get function
Object.assign(recevier,supplier);
var descriptor2 = Object.getOwnPropertyDescriptor(recevier,'name');
console.log(descriptor2.value); //file.js
console.log(descriptor2.get); // undefined
Object.setPrototypeOf
Object.setPrototypeOf设置对象的原型。
let person = {
getGreeting(){
return "Hello";
}
};
let dog = {
getGreeting(){
return "Woof";
}
};
// prototype is person
let friend = Object.create(person);
console.log(friend.getGreeting()); // "Hello"
console.log(Object.getPrototypeOf(friend) === person); // true
// set prototype to dog
Object.setPrototypeOf(friend,dog);
console.log(friend.getGreeting()); // "dog"
console.log(Object.getPrototypeOf(friend) === dog); // true
上面代码通过setProtoType方法改变了friend的protoType。
super
super这个关键字,既可以当作函数使用,也可以当作对象使用,super作为函数调用时,代表父类的构造函数。ES6要求,子类的构造函数必须执行一次super函数,当super作为对象时,super指的是当前对象的原型对象。下面的例子中super当做对象来使用。
重构原型对象方法时,如果使用es5方式书写可能会有如下报错:
/**es5**/
let person = {
name:'person',
getGreeting() {
return "Hello";
}
};
// prototype is person
let friend = {
name:'friend',
getGreeting() {
return Object.getPrototypeOf(this).getGreeting.call(this) + ", hi!";
}
};
Object.setPrototypeOf(friend, person);
// prototype is friend
// 也可以修改成
// let relative = {};
// Object.setPrototypeOf(relative, friend);
let relative = Object.create(friend);
console.log(friend.getGreeting()); // "Hello"
console.log(friend.getGreeting()); // "Hello hi!"
console.log(relative.getGreeting()); // error!
relative的prototype为friend,relative.getGreeting() 执行时 Object.getPrototypeOf(this)为friend,this为relative,调用时又将this指向了relative,造成了死循环,导致内存溢出。
使用super便不会产生此情况。
/**es6 super**/
let person = {
name:'person',
getGreeting() {
return "Hello";
}
};
let friend1 = {
name:'friend',
getGreeting:function() {
return super.getGreeting() + ", hi!";
}
};
// error in friend1
Object.setPrototypeOf(friend1, person);
console.log(friend1.getGreeting()); // "error"
// prototype is person
let friend = {
name:'friend',
getGreeting() {
return super.getGreeting() + ", hi!";
}
};
Object.setPrototypeOf(friend, person);
let relative = Object.create(friend);
console.log(friend.getGreeting()); // "Hello"
console.log(friend.getGreeting()); // "Hello hi!"
console.log(relative.getGreeting()); // "Hello hi!"