深拷贝TS转译核心--Object.slice()
/* 深拷贝 */
var a = [1,2,3]
var b = [...a] // ES6 数组展开
var c = {'a':1,'b':2}
var d = {...c} // ES2018 新增对象展开
// 展开出的内容都是深拷贝内容
// 一个完备的深拷贝,往往需要考虑数组内是否含有对象的情况
// 网上垃圾教程太多,最好自行理解一下,掌握最简写法
// 下面是 tsc 对本文件 .ts 的转译 .js(转译至ES5版)
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var a = [1, 2, 3];
var b = a.slice();
var c = { 'a': 1, 'b': 2 };
var d = __assign({}, c);
有关知识点:
展开语法,迭代器(Symbol.iterator),call和apply绑定,function arguments,||(短路或),对象属性查询,数组slice用法
我的最简写法:
Object.assign() FF34+
// 针对普通数组对象的拷贝
var deepcopyarr = (...arr) => Object.assign([], arr.reduce((acc,cur) => [...acc, ...cur]))
var deepcopyobj = (...obj) => Object.assign({}, ...obj)
测试用例
var a0 = {'a':1}
var a1 = deepcopyobj(a0)
a0.a = 2
console.log(a0, a1) // {'a':2} {'a':1}
var b0 = {'a':1}
var b1 = {'b':2}
var b2 = deepcopyobj(b0,b1)
console.log(b2) // {'a':1,'b':2}
var c0 = [1,2,3]
var c1 = deepcopyarr(c0)
c0 = [4,5,6]
console.log(c0, c1) // [4,5,6] [1,2,3]
var d0 = [1,2,3]
var d1 = [3,4,5]
var d2 = deepcopyarr(d0,d1)
console.log(d2) // [1,2,3,3,4,5]
MDN上关于拷贝访问器
const obj = {
foo: 1,
get bar() {
return 2;
}
};
let copy = Object.assign({}, obj);
console.log(copy); // { foo: 1, bar: 2 } copy.bar的值来自obj.bar的getter函数的返回值
下面这个函数会拷贝所有自有属性的属性描述符
function completeAssign(target, ...sources) {
sources.forEach(source => {
let descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {});
// Object.assign 默认也会拷贝可枚举的Symbols
Object.getOwnPropertySymbols(source).forEach(sym => {
let descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
}
copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }