关于值传递和引用传递,这个我觉得首先我们应该先去了解Javascript的堆和栈,基本类型和引用类型这些概念。
在计算机领域中,堆栈是两种数据结构,它们只能在一端(称为栈顶(top))对数据项进行插入和删除。
- 堆:队列优先,先进先出;由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 栈:先进后出;动态分配的空间 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。
在Javascript中呢,可以按照数据类型分为两大类,基本类型和引用类型。
1. 基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
2. 引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向引用类型的值。
举个简单的例子我们就能很快发现它们之间的区别:
let a = 5, b;
b = a; // b = 5
a = 6; // b = 5
当前操作将a变量的值直接复制给了b变量,而a变量再次发生改变的时候,b变量依旧是之前的值,不会跟随着a变量的值改变而发生改变。像这种数字,字符串,布尔等基本类型之间的值的复制,就叫做值传递。
我们在来看看在数组,对象这些引用类型之间,参数的传递又会有什么不同:
lat a = {name: '名字', type: '引用传递'}, b;
b = a; // b = {name: '名字', type: '引用传递'}
a.name = '我是a';
console.log(b); // b = {name: '我是a', type: '引用传递'}
let arr = [1, 5, 6], arr1 = [];
arr1 = arr;
arr[0] = 6;
console.log(arr1); // arr1 = [6, 5, 6]
在当前操作中,a的地址指向了我们定义的内容,然后我们将a指向的地址赋给了b,b此时保存的并不是一个对象的数据,而是一个地址,当改变a对象属性的时候,地址指向的对象属性发生的改变,b保存地址的对象发生改变,b的值同时跟随改变了。数组也同样是这个道理。像这种引用类型之间的地址指向的复制,就叫做引用传递。
在实际开发中,尤其是在使用MVVM框架的时候,应该会常常碰到这个问题吧(至少我在使用刚开始VUE开发的时候碰到挺多这种类型的问题),为了避免引用传递带来的麻烦(有时候非常好用),我一般都通过改变地址的方法去拿到自己想要的数据。
1.新建对象或者数组
let arr = [];
this.oldData.find(item => {
let obj = {};
obj.name = item.name;
obj.type = item.userType;
..........
arr.push(obj)
})
this.newData = arr;
2. 深拷贝(深度拷贝就是把父对象拷贝到子对象上,而且两者的内存和以后的操作都互不影响的拷贝)
let newData = JSON.parse(JSON.stringify(obj))
目前我使用多的就是这两种方法了。
以上。