JavaScript 中有两种不同的数据类型的值,分别是基本数据类型和引用数据类型

  • 基本数据类型:Number、String、Boolean、Null、Undefined
  • 引用数据类型:Array、Date、Math、RegExp、Object、Function ……

变量赋值的时候,基本数据类型时传值的,也就是直接访问。引用数据类型是按引用访问的,相当于 C 中的指针。

基本类型的赋值

修改其中一个变量不会影响另一个变量的值

1
2
3
4
5
6
var x = 1
var y = x
y = 2

console.log(x)
//结果还是1

如果从一个变量向另一个变量复制基本类型的值,会在变量变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上
——《JavaScript高级程序设计》

也就是说,传值得过程经历了以下几步:

  1. 复制变量的值
  2. 申请一个新的内存地址保存复制的值
  3. 把复制的值的新地址赋给新的变量

所以两个变量的值只是在数值上相等,其实在内存中是两个地址,是互相独立的存在

因此其中一个发生改变时并不会影响到另外一个

引用数据类型赋值

引用数据类型的赋值,是把传递存放数据的内存空间的地址

1
2
3
4
5
var arr1 = [1,2,3,4];
var arr2 = arr1;
arr2[0] = 10;

console.log(arr1[0]); //10

当从一个变量向另一个变量复制引用的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上引用同一个对象
——《JavaScript高级程序设计》

克隆实现传值

克隆实现原理:

  • 利用字符串赋值为传值的特点,先将对象转化成字符串形式
  • 然后将字符串形式再转换成对象

for 循环

这种方法在遇到复杂数组时比较无力,比如 arr = [1,[2,3],{a:1,b:2}]

1
2
3
4
5
6
7
8
9
10
//for循环原数组,将每个参数分别赋值给空数组arr2
//缺陷是:当数组中存放了引用类型数据时,就需要多次循环,比较复杂
var arr1 = [1,2,3,4]
var arr2 = []
for (var i = 0; i<arr1.length; i++){
arr2[i] = arr1[i]
}
arr2[0] = 10;

console.log(arr1[0]); //1 arr1不受影响

forEach 实现

forEachES5 新引入的数组方法,可以用来循环数组及对象

1
array.forEach(callback,[thisObject]);

forEach 有两个参数:第一个参数是回调函数,第二个参数是执行回调是 this 的值
回调函数包含 3 个参数:

  1. 当前循环值
  2. 当前循环下标
  3. 被循环的数组本身

注意:ie浏览器 没有 forEach 方法,要兼容的话需要自己用原生给原型链上加这个方法

1
2
3
4
5
6
7
8
9
10
11
12
var arr1 = [1,2,3,4];
var arr2 = [];
var str = '';
arr1.forEach(function(val){
console.log(val) //1 2 3 4 这里val是循环值
str += val;
});
arr2 = str.split('')
console.log(arr2) //["1","2","3","4"] 此处arr已经是数组
arr2[0] = 10; //改变arr2中的参数

console.log(arr1[0]) //1 arr1不受影响

JSON.stringify() / JSON.parse() 实现

  • JSON.stringify():把对象转换成字符串形式的 JSON 格式字符串值(无法转换 DOM/BOM 对象)
  • JSON.parse():把字符串形式的标准 JSON 字符串转换成对象(属性名称必须有引号)

用法举例:

1
2
3
4
5
var arr = [1,2,[3,4],{a:'abc',b:true}];
console.log(JSON.stringify(arr)) //'[1,2,[3,4],{"a":'abc',"b":true}]' 属性会加上双引号

var oDiv = document.getElementById('div1')
console.log(JSON.stringify(oDiv)) //{} 打印一个空对象

克隆实现方法:

1
2
3
4
5
6
var arr1 = [1,2,[3,4],{a: 'abc',b: true}];
var arr2 = JSON.stringify(arr1);
arr2 = JSON.parse(arr2);
arr2[2][0] = 10;

console.log(arr1[2][0]) //3 arr1不受影响