ES6 - 创建对象

关于 ES6 中对象语法增强。

一、初始化对象

  • new Object()
  • Object.create()
  • 字面量标记法

可使用以上三种方法初始化一个对象。

1
2
3
4
let 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
10
let a = 1;
let b = 2;
let objES5 = {
a:a,
b:b
}
let objES6 = {
a,
b
}

以上代码实现的效果一样。

二、ES6 | ES5 对比

1、动态使用 key

1
2
3
4
5
6
7
8
9
10
11
12
13
let name = 'a';   // 我想得到 obj={a:1},如果使用 let obj = {  name : 1} 那么键名只能是 name , ES5 的做法是:
let obj = {};
obj[name] = 1; // 此时,obj = { a : 1};
// 而 ES6 的实现方法为
let obj2 = {
[name] : 1
}
// 此方法为动态属性名,还可实现如下操作:
let a = 2;
let obj3 = {
[a*a + a / 2 + a/3] : 1
}
// obj 为 {5.666666667:1}

2、浅拷贝和深拷贝

写一个小 Demo , 如何实现 a==1&&a==1&a==3 为 true

1
2
3
4
5
6
7
8
let 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
23
let 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
6
let 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() 的作用是对已经定义了 getset 方法的对象或者未定义需要修改 getset 方法的对象进行重新定义。

1
2
3
4
5
var function          // 报错,function 为关键字
var null // 报错,null 为关键字
var this // 报错,this 为关键字
var undefined = 1 // 未报错
undefined // 尽管已经赋值,但是仍返回 undefined

出现以上问题的原因主要因为 undefined 是 window 的只读属性。