Object.assign()从认识到实现

1.这是个什么:

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

MDN这样说。

    • let newObj=Object.assign(target,...source)//target为目标对象    source为源对象
  • 常见特性:
    1. 只能够复制源对象中可枚举的属性,继承得以及enumerable:false的属性都不能被拷贝。
    2. 对于目标对象中已经存在的属性,源对象将会根据在arguments中的顺序进行依次覆盖。
    3. assign为浅拷贝,基本类型进行拷贝,引用类型进行拷贝。

      let a={
          name:132,
          age:44,
          previous:{
              limit:'old'
          }}
      let b=Object.assign({},a);
      console.log(b); //{ name: 132, age: 44, previous: { limit: 'old' } }
      a.name='new name';  
      a.previous.limit='new';
      console.log(b); //{ name: 132, age: 44, previous: { limit: 'new' } }复制代码

    4. 目标对象不能为nullundefined,这里可以看看Object.assign()的对于targetnullundefined时的原生表现。

      let b={
          name:132,
          age:44,
          previous:43242}
      let c={
          previous:'dsfs0'
      }
      let d=Object.assign(null,b,c);  //Cannot convert undefined or null to object复制代码

2.实现一个Object.assign()

  • 思路:
    1. 先对target对象进行检测是否为null || undefined,是的话抛出TypeError
    2. Object.defineProperty定义assign2属性。
    3. Object()target包装为一个对象to
    4. arguments中的源对象依次进行属性遍历(for...of...)用Object.hasOwnProperty进行属性检查,有则进行覆盖,没有则创建属性进行赋值(址)。
    5. 返回新对象to
  • 知识储备:
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
  1. 这个方法会有个默认行为需注意:

    Object.defineProperty(target,key,{
        // enumerable:false,
        // writable:false,
        // configurable:false,
    })复制代码

这对我们还原assign原生行为很重要。

Object
构造函数创建一个对象包装器。
hasOwnProperty() 方法会返回一个布尔值,指示对象 自身属性中是否具有指定的属性。

该方法会判断属性是否属于对象实例,来自原型和继承得的属性将不会被遍历。

  • 具体实现(直接上代码了)

    if(typeof Object.assign2 !=='function'){    Object.defineProperty(Object,"assign2",{        value(target){            'use strict'            if(target==null){       //underfined  null  两种非法情况                throw new TypeError("danger type error");            }            let to=Object(target);            for(let index=1;index<arguments.length;index++){                let nextSouce=arguments[index];                if(nextSouce!==null){                    for(let nextKey in nextSouce){                        if(!Object.prototype.hasOwnProperty.call(to,nextKey)){                            to[nextKey]=nextSouce[nextKey];                        }else{                            if(to[nextKey]!==nextSouce[nextKey]){                                to[nextKey]=nextSouce[nextKey];                            }                        }                    }                }            }            return to;        },        writable:true,        configurable:true    })} 复制代码

  • 要注意什么...
    • 为什么使用Object.defineProperty来定义assign2属性。
  • 先来看一段代码

    console.log(Object.keys(Object))    //[]复制代码

  • 很明显看到Objectassign方法是不能被遍历到的,然而如果我们直接用下面这种方式定义,我们再看一下结果。

    Object.assign2=function(){}console.log(Object.getOwnPropertyDescriptor(Object,'assign2'))/* { value: [Function],    writable: true,    enumerable: true,                //注意这里    configurable: true } */
    
    //而对于原生assign
    console.log(Object.getOwnPropertyDescriptor(Object,'assign'))/* { value: [Function],    writable: true,    enumerable: false,    configurable: true  } */复制代码

      • 根据前面说的Object.defineProperty的默认行为,这里使用它就显得很合理了。
    • 为什么使用严格模式'use strict'
      • 我们先来看一个东西

        let obj=Object('123');console.log(Object.getOwnPropertyDescriptor(obj,'0'))// { value: '1',//   writable: false,  //注意这里只读//   enumerable: true,//   configurable: false // }复制代码

      • 对于只读的属性,Object.assign()对于只读属性的处理情况是

        let obj=Object.defineProperty({},'0',{    value:'123',})let newObj=Object.assign(obj,{0:456});console.log(newObj)
        //报错 TypeError: Cannot assign to read only property '0' of object '#<Object>'复制代码

      • 而原生js对于只读属性修改时只会静默失败,不会报错,在严格模式下报错,所以我们这里开启严格模式。
    • 前面说过targetnull || undefined时会报错。所以我们应该对这两种情况进行检查,为什么我们只判断了是否等于null呢,看代码

      console.log(null==undefined)    //trueconsole.log(null === undefined)     //false复制代码
      • 看到这里应该理解了。
    • 为什么我们用Object.prototype.hasOwnProperty.call来检测属性呢,来看一种情况

      let obj=Object.create(null);console.log(Object.getOwnPropertyDescriptor(obj,'assign'))复制代码

      • 当我们以null为原型创建新对象时,此时创建的对象是没有指向原型链的,所以定义在Object.prototype上的hasOwnProperty方法就不能被访问到.

Object.create()

方法使用现有对象作为新创建对象的原型来创建新对象



转载于:https://juejin.im/post/5c7fb037f265da2d9c389829

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值