在 JavaScript 的 ECMAScript 2017 规范中,一个新的功能是getOwnPropertyDescriptors
方法,简而言之,这种方法会返回给定对象的所有属性的信息,包括关于 getters 和 setters 的信息,它允许我们创建对象的副本并克隆它,同时复制所有属性,包括 getters 和 setters。
在JavaScript中,我们可以创建特殊的属性,它们作为对象内部的方法行为,并作为对象外部的属性行为,它们被称为得到
和设置
。
1// object with get and set properties
2
3const gator = {
4 name: 'Ben',
5 type: 'reptilian',
6 get fullName(){
7 return `${this.name}${this.type}`;
8 },
9 set gatorName(name){
10 this.name = name;
11 }
12};
如果我们做‘console.log(gator)’,我们只会得到名称和类型,然而,我们仍然可以访问 fullName 接口,尽管它在控制台上看不见。
1console.log(gator) // {name: 'Ben', type: 'reptilian',}
2console.log(gator.fullName) // 'Benreptilian'
<$>[注] 请注意,我们将getter称为通常的属性,而不是方法。
克隆物体
我们使用Object.assign()
来克隆JavaScript中的对象. 如果您不熟悉Object.assign方法,请阅读JavaScript中的《如何管理对象》(https://andsky.com/tech/tutorials/js-dealing-with-objects)文章。 这种方法的主要问题是,当我们克隆对象时,结果并不完全如我们所期望的那样。
1const cayman = {Object.assign({}, gator};
2console.log(cayman) // {name: 'Ben', type: 'reptilian', fullName: Benreptilian, gatorName: undefined }
因此,getter 和 setter 成为常见值,如果 getter 是对比值,则 setter 将是未定义的。
让我们用getOwnPropertyDescriptors
方法克隆对象。
1const crocodilian = Object.defineProperties({}, Object.getOwnPropertyDescriptors(gator)));
现在让我们比较我们所拥有的每个对象的描述器:
1console.log(Object.getOwnPropertyDescriptors(gator));
2
3/* name: {value:'Ben', writable: true, enumerable: true, configurable: true},
4 type: {value:'reptilian', writable: true, enumerable: true, configurable: true},
5 fullName: {get: f, set: undefined, enumerable: '', configurable: ''},
6 gatorName: {get: undefined, set: f, enumerable: '', configurable: ''},
7*/
8
9console.log(Object.getOwnPropertyDescriptors(cayman));
10
11/* name: {value:'Ben', writable: true, enumerable: true, configurable: true},
12 type: {value:'reptilian', writable: true, enumerable: true, configurable: true},
13 fullName: {value: 'Benreptilian', writable: true, enumerable: '', configurable: ''},
14 gatorName: {value: undefined, writable: true, enumerable: '', configurable: ''},
15*/
16
17console.log(Object.getOwnPropertyDescriptors(crocodilian));
18
19/* name: {value:'Ben', writable: true, enumerable: true, configurable: true},
20 type: {value:'reptilian', writable: true, enumerable: true, configurable: true},
21 fullName: {get: f, set: undefined, enumerable: '', configurable: ''},
22 gatorName: {get: undefined, set: f, enumerable: '', configurable: ''},
23
24*/
gator
的对象属性name
和type
被定义为常规属性,但 fullName 和 gatorName 被定义为 getter 和 setter. 它们没有值
字段,但有get
和set
字段. cayman
的对象 getter 和 setter现在被描述为常规值。
getOwnPropertyDescriptors
方法有助于避免数据丢失,通过它,我们可以创建对象的深度副本,而不依赖另一个实用功能。