deepClone, extend, 深克隆对象和Object.assign(ES6)

在看 you might not need jQuery的时候(外网打不开,这是个博客园转过来的),看到了$.extend函数来拷贝某个对象。测试了一下原文代码,居然复制不到深层的。原代码如下:

var deepExtend = function(out) {
  out = out || {};//问题就出在这里!

  for (var i = 1; i < arguments.length; i++) {
    var obj = arguments[i];

    if (!obj)
      continue;

    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        if (typeof obj[key] === 'object')
          deepExtend(out[key], obj[key]);
        else
          out[key] = obj[key];
      }
    }
  }

  return out;
};

deepExtend({}, objA, objB);

这里虽然直接对out赋值了,但可能出现的情况是,原始的target对象容器中(第一个参数,即Out),out[key]为undefined,那么如果确定out[key]的类型为对象的情况下,才是指向同一个对象,否则并没有改变out[key]的值。

修改代码如下,将这一步提到前面,同时润色代码增加报错信息:

function extend(out){

    if(!out){

        console.error('where is your container ?')
    }

    var objs = [].slice.call(arguments,1)

    if(objs.length > 0){

        objs.forEach(function(item,index){

            if(typeof item !== 'object'){

                console.error('item' + index + ' is no valid arguments, expected to be object')

            }

            else {

                for(var key in item){

                    if(item.hasOwnProperty(key)){

                        if(typeof item[key] === 'object'){

                            out[key]= out[key] || {}  // 这步是最重要的!

                            extend(out[key],item[key])

                        }

                        else{

                            out[key] = item[key]
                        }
                    }

                }

            }

        })

    }

    else{

        console.error('no objs to be copy')
    }

    return out;
}

var output = extend({a:{c:2},f:'fuck'},{a:1},{
    b:{
        lala:'name'
    }
})

这样就可以达到深克隆的目的了。当然除了JQuery, zepto、 Lodash、underScore、Prototype等库都实现了这个工具。ES6中的Object.assign也原生提供了相应的功能。

Object.assign() 方法值能复制可枚举、本身的属性(enumerable and own properties), 它用在引用源上使用get方法,在目标容器上使用set方法,引发了getters、setters。因此,如果在融合的源对象含有getter的话,会不适用。如果要复制属性的定义,包括其可枚举性,应该使用Object.getOwnPropertyDescriptor()和Object.defineProperty()。

对深克隆,不可使用Object.assign() 方法,因为它只会复制对象的引用而不是新建一个对象。最简单的深克隆方法某过于此,但只能复制可枚举类型的。

let target = JSON.parse(JSON.stringify(source))

因此,对深克隆,最好还是用extend方式层层递归,直到把源对象的属性拆到不是对象而是plain value为止。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值