一深拷贝
1 为什么要深拷贝
js 中的引用类型变量的直接复制是浅拷贝,挡在操作被复制变量的时候,是会影响复制变量的。这种会在函数使用的时候造成一定的困然。
var person = {
name:"张三",
age:15,
}
function changeName(person){
person.name = "李四";
return person;
}
var person2 = changeName(person);
alert(person.name); // 李四
alert(person2.name);// 李四
据上,我们生成了一个新的对象person2。但是看到person的name 也被改变了,但是在很多时候我们是不希望person的内容被修改的时候。我们就需要深拷贝。让新变量和老变量的内存也改变。
2 深拷贝的方法
2.1 递归
创建一个深拷贝方法
//使用递归的方式实现数组、对象的深拷贝
function deepClone1(obj) {
//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
var objClone = Array.isArray(obj) ? [] : {};
//进行深拷贝的不能为空,并且是对象或者是
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepClone1(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
这个方法主要针对数组和对象类型
2.2 通过json 方法
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
2.3 通过第三方的插件
lodash 函数库中的cloneDeep方法,JQ中的extend方法,以及Object.assign()都可以实现深拷贝。
但是需要注意Object.assign() 在一层属性的时候是深拷贝,但是第二层属性就是浅拷贝了
//示例1 一层深拷贝
let obj = {a:1}
let newObj = Object.assign({},obj);
console.log(newObj); //{a: 1}
newObj.a=2;
console.log(obj); //{a:1}
console.log(newObj); //{a: 2}
//示例2 二层浅拷贝
let obj = {a:1,b:{name:"zhangsan"}}
let newObj = Object.assign({},obj);
console.log(newObj); //{a:1,b:{name:"zhangsan"}}
newObj.b.name="lisi";
console.log(obj); //{a:1,b:{name:"lisi"}}
console.log(newObj); //{a:1,b:{name:"lisi"}}
二 闭包
闭包是为了能够读取其他函数内部的变量,也就是为了让函数中的变量不会被垃圾回收机制回收,而一直存在于内存中
闭包实例:
function f1(){
n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
如何证明闭包后函数中的变量一直存在于内存中
function f1(){
var n=999;
nAdd=function(){n+=1}
return n;
}
var result=f1();
console.log(result); // 999
nAdd();
console.log(result); // 999
这里的nAdd函数因为用var 所以提升成了全局变量,可以在外面执行。但是并不会改变result。因为执行到nAdd中内部时候,执行完,变量就被释放了。
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
形成闭包之后,fi中的变量n会一直存在内存中,在第二次调用result()方法的时候,这个时候的n 已经在之前的nAdd方法由999变成了1000。
会产生这个的原因主要就是因为f2被赋值给了一个全局变量,所有身为f2的父函数,他也必须一直存在,这样f2才能生存(用词可能不当)。
也是因为闭包会让函数内部的变量一直存在于内存中,也就导致了使用闭包会产生一些性能消耗。