JavaScript有五种基本数据类型(Undefined, null, Boolean, String, Number),还有一种复杂的数据类型,就是对象。
Undefined 其实是已声明但没有赋值的变量的输出结果,null其实就是一个不存在的对象的结果
- 对于简单的数据类型
它们值在占据了内存中固定大小的空间,并被保存在栈内存中。 当一个变量向另一个变量复制基本类型的值时,会创建这个值的副本,还有就是不能给基本类型的值添加属性。
12
3
4
var a = 1;var b = a;
a.attr = ‘long‘;
console.log(a.attr) //undefined
上边代码中a就是简单数据类型(number),b就是a的副本,它们两者都占有不同位置,但相等的内存空间。
- 对于复杂的数据类型
复杂的数据类型即引用类型,它的值是对象,保存在堆内存中,包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针。从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象。
12
3
4
5
6
7
8
var 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
12
3
4
5
var 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
12
3
4
var 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); |