我们知道js中那些是值类型,那些是引用类型,这是必须要搞清楚。
JavaScript中的值类型:数值、布尔值、null、undefined
JavaScript中的引用类型:对象、数组、函数
堆栈
栈(stack)
由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。一种先进后出的数据结构。堆(heap)
动态分配的内存,大小不定也不会自动释放。队列优先,先进先出。
值类型是存放在栈中的基本类型,对象数据则是在堆中创建并在栈中保留对象在堆中的地址。我们从下面的例子来理解
var a = [1,2,3,4,5];
var b = a;
var c = a[0];
数据在内存中的存储示意图(图片来自‘小辉_Ray’的博客)
通过变量在内存中的存储我们可以看出来,所有的变量都是在栈内存中存在的,不同的是值类型存放的是值本身,引用类型存放的是指向堆内存对象的地址。
基本类型与引用类型最大的区别实际就是传值与传址的区别。
var a =1;
var array = [1,2,3];
var object = {a:1,b:2,c:3};
function reassign(num,arr,obj){
//将参数重新赋值
num = '';
//arr 是array对象的引用拷贝,我们把这个引用重新赋值,这时的arr不在指向array所指向的对象,而是指向新的空数组
//所以这时候我们再对arr进行操作,将不会影响array。
//obj同理
arr = [];
arr.push(123);
obj = '';
}
function operate(num,arr,obj){
num = 2;
arr.push(4);
obj.test = 'test';
// 我们直接对传递的参数进行操作,
// 参数num是值类型,传递的是参数a的值拷贝,所以我们对num进行操作不会影响外层的a变量
// arr,和obj,一个是数组,一个是对象,都是引用类型,传递的是对象地址的拷贝,我们对它的操作也会影响到外层变量的值,因为他们都指向相同的堆对象。
}
reassign(a,array,object);
console.log(a); // 1
console.log(array); // [1,2,3]
console.log(object); // {a:1,b:2,c:3}
operate(a,array,object);
console.log(a); // 1
console.log(array); // [1,2,3,4]
console.log(object); // {a:1,b:2,c:3,test:'test'}
对象的拷贝
js 深拷贝 vs 浅拷贝
浅拷贝
//如果对象的属性是引用类型,对对象的属性进行拷贝时,拷贝的只是对象属性的引用
function Copy(object) {
var temp = {};
for (var property in object) {
temp[property] = object[property];
}
return temp;
}
var obj = {}
obj.a = "abc";
obj.b = [1,2];
var copyObj = Copy(obj);
console.log(copyObj); // { a: 'abc', b: [ 1,2] }
copyObj.b.push(3); //这里向copyObj的b属性中push一个值,原始的obj对象也会受到影响,因为数组是引用类型
console.log(obj); //{ a: 'abc', b: [ 1, 2, 3 ]}
深拷贝
// 实际编码中,很多时候浅拷贝并是我们想要的,我们希望拷贝完成后的对象和原对象不再有任何关联。
// 深拷贝
function Copy(source, target) {
var target = target || {};
for (var i in source) {
if (typeof source[i] === 'object') { //这里有个疑问, 如果对象的属性是函数呢?
target[i] = (source[i].constructor === Array) ? [] : {};
Copy(source[i], target[i]);
} else {
target[i] = source[i];
}
}
return target;
}
var obj = {}
obj.a = "abc";
obj.b = [1,2];
obj.c = function(){};
var copyObj = Copy(obj);
copyObj.b.push(3); //这里向copyObj的b属性中push一个值,原始的obj对象也会受到影响,因为数组是引用类型
console.log(copyObj); // { a: 'abc', b: [ 1,2] }
console.log(obj); //{ a: 'abc', b: [ 1, 2, 3 ]}
网友评论