JavaScriptES6对象的Object.getOwnPropertyDescriptors方法理解

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/c__dreamer/article/details/81611117

上一个博客提到了Object.getOwnPropertyDescriptor方法会返回某个对象属性的描述对象。ES2017引入了Object.getOwnPropertyDescriptors方法。返回值为对象所有自身属性(非继承属性)的描述对象。

const obj = {
     a : 1,
     foo(){},
     get bar(){
        return 1;
     }
}
console.log(Object.getOwnPropertyDescriptors(obj));

Object.getOwnPropertyDescriptors方法的实现原理很简单

const getOwnPropertyDescriptors = (obj) => {
     let result = {};
     for(let key of Reflect.ownKeys(obj)){
        result[key] = Object.getOwnPropertyDescriptor(obj,key);
    }
    return result;
}

该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。

const source = {
     set foo(value){
         console.log(value);
     }
}
const target = {};
Object.assign(target,source);
console.log(target);        //{ foo : undefined}
console.log(Object.getOwnPropertyDescriptor(target,"foo"));

上面代码中,source对象的foo属性的值是一个赋值函数,Object.assign方法将这个属性拷贝给target1对象,结果该属性的值变成了undefined。这是因为Object.assign方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。 这时,Object.getOwnPropertyDescriptors方法配合Object.defineProperties方法,就可以实现正确拷贝。

//Object.getOwnPropertyDescriptors拷贝对象方法
const shallMerge = (target,source) => Object.defineProperties(target,Object.getOwnPropertyDescriptors(source));

Object.getOwnPropertyDescriptors方法的另一个用处,是配合Object.create方法,将对象属性克隆到一个新对象上面。这属于浅拷贝。

//getPrototypeOf方法是读取该对象的__proto__
const shallowClone = (obj) => Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj));
let obj = {
     a : 1,
}
console.log(shallowClone(obj));

另外,Object.getOwnPropertyDescriptors方法可以实现一个对象继承另一个对象。ES6 规定__proto__只有浏览器要部署,其他环境不用部署。

const shallowExtend = (target,source) => Object.create(target,Object.getOwnPropertyDescriptors(source));

Object.getOwnPropertyDescriptors也可以用来实现Mixin(混入模式)。

const mix = (object) => ({
    with : (...mixins) => mixins.reduce(
        (c,mixin) => Object.create(
             c,Object.getOwnPropertyDescriptors(mixin)
        ),object),
})
let a = {a : "a"};
let b = {b : "b"};
let c = {c : "c"};
let d = mix(c).with(a,b);
for(let key in d){
     console.log(key);       //b  a   c
}
//上面代码b继承了a,把c对象混入了原型a上

主页传送门

展开阅读全文

没有更多推荐了,返回首页