JavaScript有五种基本数据类型(Undefined, null, Boolean, String, Number),还有一种复杂的数据类型,就是对象。
Undefined 其实是已声明但没有赋值的变量的输出结果,null其实就是一个不存在的对象的结果
-
对于简单的数据类型
它们值在占据了内存中固定大小的空间,并被保存在栈内存中。 当一个变量向另一个变量复制基本类型的值时,会创建这个值的副本,还有就是不能给基本类型的值添加属性。1234var a = 1;var b = a;a.attr = 'long';console.log(a.attr) //undefined上边代码中a就是简单数据类型(number),b就是a的副本,它们两者都占有不同位置,但相等的内存空间。
-
对于复杂的数据类型
复杂的数据类型即引用类型,它的值是对象,保存在堆内存中,包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。12345678var obj = {name: 'long',age: 0};var obj2 = obj;obj2.c = 5;console.log(obj); //Oject {name: 'long', age: 0, c: 5}console.log(obj2); //Oject {name: 'long', age: 0, c: 5}
我们可以看到obj赋值给obj2后,当我们更改其中一个对象的属性值,两个对象都发生了改变,究其原因是因为obj和obj2这两个变量都指向同一个指针,赋值是复制了指针,所以当我们改变其中一个值,就会影响另一个变量的值。
浅拷贝
其实上边的代码就是浅拷贝,有时候我们只是想备份数组,但是只是简单让它赋给一个变量,改变其中一个,另外一个就紧跟着改变,但很多时候这不是我们想要的。
1
2
3
4
5
6
7
8
|
var obj = {
name:'wsscat',
age:0
}
var obj2 = obj;
obj2['c'] = 5;
console.log(obj);//Object {name: "wsscat", age: 0, c: 5}
console.log(obj2);////Object {name: "wsscat", age: 0, c: 5}
|
深拷贝
数组
对于数组我们可以使用slice()和concat()方法来解决上面的问题。
-
slice
12345var arr = ['ge', 'yu', 'long'];var arrCopy = arr.slice(0);arrCopy[0] = 'gai';console.log(arr) // ['ge', 'yu', 'long']console.log(arrCopy) // ['gai', 'yu', 'long'] -
concat
1234var arr = ['ge', 'yu', 'long'];var arrCopy = arr.concat();arrCopy[0] = 'gai';//console跟上边一样
对象
对象我们可以定义一个新的对象并遍历新的属性去实现深拷贝
原始方法:
1
2
3
4
5
6
7
8
9
10
|
var obj = {
name: 'geyulong',
age: 0
};
var obj2 = new Object();
obj2.name = obj.name;
obj2.age = obj.age;
obj.name = "gaiyulong";
console.log(obj); // Object {name: 'geyulong', age: 0}
console.log(obj2); // Object {name: 'gaiyulong', age: 0}
|
当然我们是要封装一个方法来实现深拷贝。
1
2
3
4
5
6
7
8
9
10
11
12
|
var deepCopy = function(source) {
var result = {};
for(var key in source) {
if(typeof source[key] === 'object') {
result[key] = deepCopy(source[key])
} else {
result[key] = source[key]
}
}
return result;
}
var obj2 = deepCopy(obj);
|