const obj = {
prop1 : 100,
prop2 : "字符串属性",
get bar(){return "bar返回字符串"}
}
Object.getOwnPropertyDescriptors(obj);
{prop1: {…}, prop2: {…}, bar: {…}}bar: {get: ƒ, set: undefined, enumerable: true, configurable: true}configurable: trueenumerable: trueget: ƒ bar()arguments: (...)caller: (...)length: 0name: "get bar"__proto__: ƒ ()apply: ƒ apply()arguments: (...)bind: ƒ bind()call: ƒ call()caller: (...)constructor: ƒ Function()length: 0name: ""toString: ƒ toString()Symbol(Symbol.hasInstance): ƒ [Symbol.hasInstance]()get arguments: ƒ ()set arguments: ƒ ()get caller: ƒ ()set caller: ƒ ()__proto__: Object[[FunctionLocation]]: <unknown>[[Scopes]]: Scopes[0][[FunctionLocation]]: text.html:13[[Scopes]]: Scopes[1]set: undefined__proto__: Objectprop1: {value: 100, writable: true, enumerable: true, configurable: true}configurable: trueenumerable: truevalue: 100writable: true__proto__: Objectprop2: {value: "字符串属性", writable: true, enumerable: true, configurable: true}__proto__: Object
在浏览器里运行代码,会得到上面的结果。数据很多,但能看出都是关于各个属性的特性的描述文字。
Object.getOwnPropertyDescriptors 方法返回一个对象,所有原来的对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。
现在我们知道了,我们用Object.getOwnPropertyDescriptors能够查看对象属性的特性,让我们开发的时候对这个对象心里有底。但是这个接口还有什么实际作用呢?
作用:克隆对象。
之前我们谈过,用Object.assign()能克隆对象,其原理是把一个现有的对象和一个空对象合并之后,空对象就有了现有对象的属性。这样空对象好像就变成了源对象的克隆体一样。
这种方法在通常情况下是没问题的,但是有一个前提是Object.assign()接口无法正确拷贝set属性和get属性的对象。因为assign做合并的时候,只能拷贝一个属性值,不会把它背后的赋值方法或者取值方法一同拷贝过来。所以在这种情况下,我们就可以用Object.getOwnPropertyDescriptors方法,配合Object.defineProperties方法,实现克隆对象的功能。
这种方法的原理是将源对象的所有属性描述对象,提取出来,根据这个描述对象,重新定义一个空对象的属性。代码如下:
const source = {
set foo(value) {
console.log(value);
}
};
const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target2, 'foo')
// { get: undefined,
// set: [Function: set foo],
// enumerable: true,
// configurable: true }
我们还有另一种方法,让getOwnPropertyDescriptors方法配合Object.create方法,来克隆对象
var source = {
prop1 : "prop1",
prop2 : 100;
}
// source 是源对象,我们获取source的原型对象和source的属性描述对象,根据二者生成的新对象就是source的克隆
var clone = Object.create(Object.gtPrototypeOf(source),Object.getOwnPropertyDescriptors(source));