JS变量分为基本类型和引用类型
基本类型数据包括Number, String, Boolean, Null, Undefined五种类型;
引用数据类型包括Array, Date, RegExp, Function等, 统称为Object类型。
JS变量的存储方式
基本类型变量存储在内存的栈中,栈内分别存储着变量的标识符和变量的值。
var num1 = 3;
var num2 = 5;
引用类型变量存储在内存的堆中,存储结构如下
var person = { name: "tom", age: 16, sayName: function(){ console.log(this.name); } }
基本与引用变量的区别
变量的访问方式不同
从一个变量向另一个变量复制基本类型值和引用类型值时,存在不同
访问方式
基本变量:
按值访问,即通过对保存在变量中的值进行操作
引用变量:
按引用访问,即通过变量的引用对变量进行操作,不能直接访问引用变量的内存空间
从一个变量向另一个变量复制基本类型值和引用类型值时
基本变量的复制
var num1 = 3; var num2 = num1; console.log(num1 === num2); num2 = 5; console.log(num1, num2);
num2变量值的改变并不会影响变量num1的值,num2中的3只是num1中的3的一个副本,两者相互独立,互不影响。
其复制及赋值过程如下图所示:
引用变量的复制
var person1 = { name: "tom" }
var person2 = person1;
console.log(person1 === person1);
person2.name = "lily";
console.log(person1.name, person2.name);
person2实际上从person1上复制的是一个指针,然后person1 和 person2同时指向堆内存中一个的对象,改变其中一个变量,就会影响另一个变量。
其复制与赋值过程如下:
JS深浅拷贝
JS的深浅拷贝只针对于引用类型值。
浅拷贝
如上所示引用变量的复制,当一个引用变量复制到另一个变量,新的变量和老的变量互相影响,那么称这个复制为浅拷贝。
深拷贝
当一个引用变量复制到另一个变量,新的变量和老的变量互不影响,那么称这个复制为深拷贝。
深浅拷贝的本质区别在于复制的是对象的引用还是对象实例,浅拷贝复制的是对象的引用,深拷贝复制的是对象的实例。
那么引用类型值是否可以实现深拷贝,答案是肯定的,具体思路如下:
深拷贝代码如下:
function deepClone(obj) { if(!(typeof obj === 'object' && obj)){ alert('argument error, not a object!!!'); return; } var rtn_obj = Array.isArray(obj) ? [] : {}; for (var key in obj) { if(obj.hasOwnProperty(key)) {
if(typeof obj[key] === 'obj' && obj[key]){
rtn_obj[key] = deepClone(obj[key]);
} else {
rtn_obj[key] = obj[key];
}
} }
return rtn_obj; }
var person = {name: 'tom'};
var _person = deepClone(person);
console.log(person === _person, _person);
JSON对象的stringify和parse
stringify函数是把一个js对象序列化为一个json字符串
parse函数是把一个json字符串反序列化为一个js对象
那么通过函数stringify和parse组合进行的复制是深拷贝还是浅拷贝你呢?看代码
var person = {
name: 'tom',
friends: ['lily', 'marton']
}
var person_str = JSON.stringify(person);
var _person = JSON.parse(person_str);
console.log(_person === person, _person);
_person.name = 'zhangsasn';
console.log(person, _person);
由运行结果可知,通过函数stringify和parse组合进行的复制是深拷贝。