正确理解JS中的变量赋值

正确理解JS中的变量赋值

简单理解就是数字和字符串是复制,对象和数组是地址引用。但如果是引用,如果你对参数进行重新赋值的话,会改变参数引用的地址。函数外部的数组或者对象就不会被修改。

在看到上面这句话之前,本来我是对变量赋值的概念还不是很理解的,因为最开始我就直接认为变量赋值就是字面上的复制;然而在最近的一次新项目开发中,遇到了一个变量赋值的问题,让我对变量赋值的概念有了不一样的理解,我就又直接的认为变量赋值就是地址引用。但是,这特么也是错误的理解。虽然之前对这样的理解充满着疑惑,也没有去查阅资料去解决心中的问题,就这样让这个知识点从我脑中遗失了。

由于最近几天想脑补一下JS的基础知识,提升自己的基础知识水平,所以又重新开始翻阅各种资料追根朔源。今天在群里的某大神帮助下,基本上算是比较透彻的理解了变量赋值。简单的一句话,说出了变量赋值的原理:

简单理解就是数字和字符串是复制,对象和数组是地址引用。但如果是引用,如果你对参数进行重新赋值的话,会改变参数引用的地址。函数外部的数组或者对象就不会被修改。

下面写几个例子,验证一下JS的变量赋值到底是怎样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a = 3;
var b = a;
b++;
console.log(a); // return 3;
console.log(b); // return 4;
var c = 'string';
var d = c;
c += ' is String';
console.log(c); // return 'string is String';
console.log(d); // return 'string';

此时,从上面的例子可以看出,虽然b的值加1,但是a的值没有改变,另外,c变量有一个字符串拼接过程,但d的值没有变化。从而说明数字和字符串类型的变量赋值就是复制过程。

下面再验证一下对象Object和数组Array变量的赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var arr = [1,2,3];
var brr = arr;
brr.push(4);
console.log(arr); // return [1,2,3,4]
console.log(brr); // return [1,2,3,4]
var obj = {a: 1, b: 2};
var obj2 = obj;
obj.c = 3;
console.log(obj); // return {a: 1, b: 2, c: 3};
console.log(obj2); // return {a: 1, b: 2, c: 3};

此时,从上面的例子可以得出一个结论,那就是对象Object类型与数组Array类型的变量赋值,是一个地址引用的过程。

接下来就是验证一下对参数进行重新赋值,是否会改变参数引用的地址,而函数外部的数组或者对象就不会被修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var arr = [1,2,3];
// function change(a) {
// a.push(4);
// return a;
//}
function set(a) {
a = [3,2,1];
return a;
}
//var brr = change(arr);
var crr = set(arr);
console.log(arr); // return [1,2,3]
//console.log(brr); // return [1,2,3,4]
console.log(crr); // return [3,2,1]

从上面两个例子的结果可以看出,数组Array类型的变量赋值的确是地址的引用,然后如果作为一个函数的参数被引用后被重新赋值了,那么函数外部的数组或者对象就不会被修改了,因而参数引用的地址发生了改变。如果引用的参数在函数内并不是赋值,而是修改参数里的某个属性的话,则参数引用地址不会发生变化,外部的变量属性值也会随之发生变化。

接下来的对象Object类型的变量赋值跟数组Array类型一样,你可以亲手去验证一下,这里不再举例了。

总结

对于变量的理解,一定要理解透彻,不然在平时写的代码中会出现意想不到的结果,从而让自己陷入困境。在真正理解了变量赋值的过程和原理后,才能在自己的代码中运用自如,规避各种坑。
用简单的一句总结变量赋值的过程和原理:数字和字符串类型的变量赋值即复制过程,对象Object类型和数组Array类型的变量赋值即地址引用。但如果是引用,如果你对参数进行重新赋值的话,会改变参数引用的地址。函数外部的数组或者对象就不会被修改。