前言
上一篇一道面试题引发的js数据类型传参思考,研究了下js数据在内存中的存储,在最后自然而然的想到了深拷贝和浅拷贝,篇幅所限,就放在这里了。
何为浅拷贝
沿用上一篇的图
var obj1 = {x:1, y:2};
var obj2 = obj1;
obj2.x = 3;
console.log(obj1); // {x: 3, y: 2}
复制代码
形如上面这个例子,简单的把对象obj1赋值给obj2,他们在内存中都指向相同的堆区,改变任何一个都会影响另一个,这就是浅拷贝:赋值后的数据会相互影响
深拷贝
为了解决浅拷贝的问题,自然引申出了深拷贝:赋值后的数据彼此独立,不相互影响。即obj2拥有obj1的初始数据,但obj2的数据放在堆区的另一个位置。
深拷贝原理很简单:递归遍历对象,一一赋值
直接上完整版代码:
function deepClone(from, to) {
var record = {} // 记录引用,解决对象循环引用的问题
function innerDP(from, to) {
for (var i in from) {
if (!from.hasOwnProperty(i)) {
// for...in会遍历到原型链上的可枚举属性,hasOwnProperty只访问对象实例本身的属性
continue
}
if (from[i] && typeof from[i] === 'object' && Object.keys(from[i]).length > 0 && !(record[i] && record[i] === from[i])) {
to[i] = {}
record[i] = from[i]
innerDP(from[i], to[i])
} else {
to[i] = from[i]
}
}
}
innerDP(from, to)
}
var staff1 = {
name: '张三',
company: {
title: '总监',
cid: '10006',
wage: 50000,
service: [1, 2, 3, {level: 'gold'}],
},
age: undefined,
x: null,
y: '',
getName: function () {
return this.name
}
}
var staff2 = {}
deepClone(staff1, staff2)
console.log('staff2拷贝staff1成功:', staff2)
staff2.x = 3
staff2.company.title = '程序猿'
staff2.company.service[3].level = 'silver'
console.log('staff2改变:', staff2)
console.log('staff1是否被影响:', staff1)
var btn1 = $('#btn1') // $('#btn1').context循环引用
var btn2 = {}
deepClone(btn1, btn2)
// btn2.length = 2
console.log(btn2)
console.log(btn1)
}
复制代码
对象循环引用的问题
形如这样的循环引用对象:
var a = {}; var b = {a: a}; a.b = b; // a中有b,b中有a,无限嵌套 复制代码深拷贝时会导致堆溢出报错:Uncaught RangeError: Maximum call stack size exceeded
所以deepClone采用了record记录:!(record[i] && record[i] === from[i]) 复制代码
类型判断
Object.prototype.toString.call方法
万物皆对象,Object.prototype.toString.call(value)返回的格式都是"[Object 类型]"
function valueType(value) {
var str = Object.prototype.toString.call(value)
str = str.split(' ')[1].replace(']', '')
return str
}
console.log(valueType(1)); // "Number"
console.log(valueType('1')); // "String"
console.log(valueType(undefined)); // "Undefined"
console.log(valueType(false)); // "Boolean"
console.log(valueType(Function)); // "Function"
console.log(valueType(null)); // "Null"
console.log(valueType([])); // "Array"
console.log(valueType([])); // "Object"
console.log(valueType($('#btn1'))); // "Object"
console.log(valueType($('#btn1').context)); // "HTMLDocument"
复制代码
typeof判断
typeof 1; // "number"
typeof '1'; // "string"
typeof undefined; // "undefined"
typeof false; // "boolean"
typeof Function; // "function"
typeof null; // "object"
typeof []; // "object"
typeof {}; // "object"
复制代码
984

被折叠的 条评论
为什么被折叠?



