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

来源:互联网 发布:人力资源软件 免费 编辑:程序博客网 时间:2024/05/17 23:02

在看 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为止。

原创粉丝点击