深浅拷⻉ 面试
⾸先可以通过 Object.assign
来解决这个问题,很多⼈认为这个函数是⽤来 深拷⻉的。其实并不是,Object.assign
只会拷⻉所有的属性值到新的对象 中,如果属性值是对象的话,拷⻉的是地址,所以并不是深拷⻉。
let a = {
age: 1 }
let b = Object.assign({}, a) a.age = 2
console.log(b.age) // 1
另外我们还可以通过展开运算符...
来实现浅拷⻉
let a = {
age: 1 }
let b = { ...a } a.age = 2
console.log(b.age) // 1
通常浅拷⻉就能解决⼤部分问题了,但是当我们遇到如下情况就可能需要使⽤ 到深拷⻉了
let a = {
age: 1,
jobs: {
first: 'FE'
} }
let b = { ...a } a.jobs.first = 'native'
console.log(b.jobs.first) // native
浅拷⻉只解决了第⼀层的问题,如果接下去的值中还有对象的话,那么就⼜回 到最开始的话题了,两者享有相同的地址。要解决这个问题,我们就得使⽤深拷⻉了
深拷⻉
这个问题通常可以通过JSON.parse(JSON.stringify(object))
来解决。
let a = {
age: 1,
jobs: {
first: 'FE'
} }
let b = JSON.parse(JSON.stringify(a)) a.jobs.first = 'native'
console.log(b.jobs.first) // FE
但是该⽅法也是有局限性的:
会忽略undefined
会忽略symbol
不能序列化函数 不能解决循环引⽤的对象
let obj = {
a: 1,
b: {
c: 2,
d: 3,
}, }
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
深拷贝的实现:
ES6的Object.assign()方法
针对于对象只有一层的,不能实现真正的深拷贝。对象有多层的不能使用此方法。
Object.assign({},obj1)
的意思是先建立一个空对象{},接着把obj1
中所有的属性复制过去,所以obj2
会长得跟obj1
一样,这时候再修改obj2
也不会影响obj1
。
var obj1 = {name:'lily'};
var obj2 = Object.assign({},obj1);
obj2.name = 'bob';
console.log(obj1.name); //lily
console.log(obj2.name); //bob
二:将对象转成字符串再转换回来
用JSON.stringify
把对象转成字符串,再用JSON.parse
把字符串转成新的对象。
var obj = {
a:'hello',
b:{
name:'lily',
age:21
},
c:[1,2,3]
};
var obj1 = JSON.parse(JSON.stringify(obj));
obj1.a = 'world';
obj1.b = {
name:'bob',
age:15
};
obj1.c = [6,7,8];
console.log(obj.a);
console.log(obj.b);
console.log(obj.c);
console.log(obj1.aaa);
console.log(obj1.bbb);
console.log(obj1.ccc);
此时,即使改变了obj1
里面每个属性的值,obj
也不会受影响。但这种方法不能针对函数function
,无效。
三:递归方法实现深拷贝
1:三元表达式:
表达式 (expr1) ? (expr2) : (expr3)
在 expr1
求值为TRUE
时的值为 expr2
,在 expr1
求值为 FALSE
时的值为expr3。
2:hasOwnProperty()
:用来判断一个对象是否有自己的属性
function deepClone(obj){
//先制造一个新的数组或对象,指向一个新的空间
var newObj = Array.isArray(obj) ? [] : {};
//判断obj的类型
//基本类型
if(typeof obj != 'object'){ //是普通类型的话就直接赋值,但不能直接返回obj,那样是浅拷贝
return newObj = obj;
}
//引用类型
if(obj instanceof Array){ //是数组
for(var i=0;i<obj.length;i++){
newObj[i] = obj[i];
if(typeof newObj[i] == 'object'){ //如果数组的值有对象的话,就继续递归
deepClone(newObj[i]);
}
}
}else{ //是对象
for(var key in obj){
if(obj.hasOwnProperty(key)){
if(typeof obj[key] == 'object'){ //对象中的数组和对象
newObj[key] = deepClone(obj[key]); //继续递归
}else{//对象中没有引用类型
newObj[key] = obj[key];
}
}
}
}
return newObj;
}
var obj = {
a:'haha',
b:[1,2,3],
c:function(){
console.log('hello');
}
};
var cloneObj = deepClone(obj);
cloneObj.a = 'hello,word';
cloneObj.b = [6,7,8];
cloneObj.c = function(){
console.log('world');
};
console.log(obj);
console.log(cloneObj);
每天一句中文式外语
泰语
不明白!/mai-kao-zai 卖靠哉/ don't understand!
你能帮我一下吗?/kun-que-can-dai-mai坤鹊蚕代麦/ can you help me?
我在找。/can-ha-you 蚕哈友/ I'm looking for.
迷路了。/mai-lu-za-tan卖路杂摊/Lose way.
我想去 ---。/can-ya-bai蚕亚掰---/ I want to go to ---.
火车站/sha-tan-ni-luo-huai沙潭尼摞淮/ train station?
公共汽车站/sha-tan-ni-luo-mie 沙潭尼摞咩/Bus stop
飞机场/sha-nang-bing /沙囊冰/Air Station
酒店/long-liang /隆凉/Hotel
学校/long-lian/隆帘/school