deepClone, extend, 深克隆对象和Object.assign(ES6)
在看 you might not need jQuery的时候,看到了$.extend函数来拷贝某个对象。测试了一下原文代码,居然复制不到深层的。原代码如下:var deepExtend = function(out) {Object.assign() 方法值能复制可枚举、本身的属性(enumerable and own properties), 它用在引用源上使用get方法,在目标容器上使用se
·
在看 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为止。
更多推荐
已为社区贡献1条内容
所有评论(0)