关于 ES6 中对象语法增强。
一、初始化对象
- new Object()
- Object.create()
- 字面量标记法
可使用以上三种方法初始化一个对象。1
2
3
4let a = new Object(); // ES5 方法
let b = Object.create(null); // ES6 新增
let c = Object.create(Object.prototype) // 这种写法等价于 ES5 的声明方法
let c = {};
其中,a 、 c 声明完成后,无任何属性,其原型为 Object.prototype
,而 ES6 的声明方式会生成一个无任何属性也无任何原型的空对象。但是如果调用 b.__proto__
、 b.toString()
仍会返回对象原型上的方法。
相比于 ES5 ,ES6 的对象更严格。1
2
3
4
5
6
7
8
9
10let a = 1;
let b = 2;
let objES5 = {
a:a,
b:b
}
let objES6 = {
a,
b
}
以上代码实现的效果一样。
二、ES6 | ES5 对比
1、动态使用 key
1 | let name = 'a'; // 我想得到 obj={a:1},如果使用 let obj = { name : 1} 那么键名只能是 name , ES5 的做法是: |
2、浅拷贝和深拷贝
写一个小 Demo , 如何实现 a==1&&a==1&a==3
为 true1
2
3
4
5
6
7
8let i = 0;
Object.defineProperty(window,'a',{
get(){
i++;
return i;
}
})
a==1&&a==1&a==3 // 此时为 true
在对象中,浅拷贝的意思是通过某些操作将 obj1 的值赋值给 obj2 ,当改变 obj2 中的某一属性时,obj1 也会随之改变,因为本质上他们时同个对象,这就是浅拷贝。而深拷贝两个对象之间的修改不会对另外一个对象产生任何影响。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23let obj1 = {
a : 1,
b : 100
}
let obj2 = obj1;
obj2.a = 100; // 此时 obj1.a === 100 为 true
// 为了解决这个问题,在 ES5 中常用的做法是:
let obj3 = {};
for(let key in obj1){
obj3[key] = obj1[key]
}
// 这样 obj3 的值的修改不会影响到 obj1 的值
// 这样循环对象的方式很麻烦,在 ES6 中的实现方式为:
let obj4 = Object.assign({},obj1);
// 更加精简的方法:
let obj5 = {...obj1}
// 再来个更炫的定义方法
let aa = 11;
let bb = 22;
let obj6 = {...obj1,...obj2,...obj3,aa,bb,get x(){return 'hi'}}
由于 obj1 、obj2 、obj3 中都含有 a 、 b 的值,所以谁在后面就使用谁的值。
3、变更原型
我们使用 ES6 声明一个对象的时候,let a = Object.create()
,在控制台输出 a 发现其中什么都没有,包括原型也是没有的,但是调用 a.__proto__
、 a.valueOf()
都是能访问的。1
2
3
4
5
6let b = {
sayHi:function(){
console.log('hi')
}
}
let a = Object.create(b);
此时 a.__proto__ === b
为真,即将 a 的原型赋值为对象 b 。在 ES6 中不推荐直接访问 a.__proto__
而是使用 Object.getProperty(a)
来获得。
三、Object.defineProperty()
Object.defineProperty()
的作用是对已经定义了 get
、set
方法的对象或者未定义需要修改 get
、set
方法的对象进行重新定义。1
2
3
4
5var function // 报错,function 为关键字
var null // 报错,null 为关键字
var this // 报错,this 为关键字
var undefined = 1 // 未报错
undefined // 尽管已经赋值,但是仍返回 undefined
出现以上问题的原因主要因为 undefined
是 window 的只读属性。