JavaScriptES6对象的Object.getOwnPropertyDescriptors方法理解

上一个博客提到了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上

主页传送门

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值