值的传递和引用

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

前言

最近看到很多js值得传递和引用问题,下面我们一起来研究一下

传值

值得传递,就是值得复制,复制出的值改变与否对原值不会发生影响;

1
2
3
4
5
var num1 = 10;
var num2 = num1;
console.log(num2);//10
num2 = 30;
console.log(num1,num2);//10 30

不难看出 num2的改变对num1 并没有什么变化。因为两个变量分配的两个不同的内存,所以两者不会相互影响。

再来看一个

1
2
3
4
5
6
7
8
9
10
11
12
13
function passValue()
{
var m=10;
var n=20;
passValue(m,n);//将m,n的值传递到passValue
alert(m); //将是原有的值
}
function passChange(a,b)
{
a = a+b; //这里a、b的值是复制传入的m值n值
alert(a);
}
passValue(); //30 10

我们可以看到新赋值的变量对原有变量并不影响。

引用

值得引用,顾名思义,就是用同一个值,这里的值是被分配到同一内存空间中。下面让我们来看一下。

1
2
3
4
5
6
7
8
function setName(obj){
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"

上面的代码我们看出 传入的参数是 声明的一个person对象,然后是给个属性name赋值,之后给传入的对象重新赋值声明一个新的对象,然后继续赋值上面的属性name,这样看来结果应该是Greg啊,明明都被赋值了,为什么结果却是Nicholas呢?这就涉及到引用问题,首先声明的person对象传入,name赋值,这时的name是Nicholas是没问题的,然后obj = new Object();重点在这里,此时的操作按值的传递来说应该是从新赋值。然而此时却是新创建了一块内存空间此时的新对象并不是原空间的person对象,然后新对象赋值name属性。这样我们得到的person的name属性依然是没变化的。

不是很明白?那么来让我们再看个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var v1 = []
var v2 = {};
var v3 = {};
function foo(v1, v2, v3)
{
v1 = [1];
v2 = [2];
v3 = {a:3}
}
foo(v1, v2, v3);
alert (v1); // 空白
alert (v2); // [object Object]
alert (v3.a); // undefined

上面我们看到函数里赋值后结果依然没有变化,这也就说明了赋值后的是一个新的对象,并不是分配在同一空间的值。 我们来变化一下,看看到底是不是这么回事呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var v1 = []
var v2 = {};
var v3 = {a:0};
function foo(v1, v2, v3)
{
v1.push (1);
v2.a = 2;
v3.a = 3;
}
foo(v1, v2, v3);
alert (v1); // 1
alert (v2.a); // 2
alert (v3.a); // 3

我们看到了,值变了?为什么呢~很明显这次的操作并不是覆盖原先的对象,而是对内存里的对象进行增值改值。并没有改变对象指针创建新的对象。这样我们就得到我们想要的值了,很厉害吧!

最后

让我们看一下这两个小例子:

1
2
3
4
5
6
var num = 10;
function numChange(num){
num = 20;
}
numChange(num);
console.log(num); //10

有没有人觉得结果不对应该是20呢?num在函数内部并没有局部的声明,然后赋值20 为啥值还是10呢?说之前来让我们看一下下面的例子:

1
2
3
4
5
6
var num = 10;
function numChange(){
num = 20;
}
numChange()
console.log(num); //20

咦?结果是20,这次覆盖了全局的num,好了,让我们看一下第一个的执行顺序numChange()执行,传入值为10的参数这是这时函数内部声明了这个num(局部变量),赋值20,我们都知道函数作用域的局部变量是不会覆盖全局变量的,所以num值依然是10,我们再来看第二个,我们并没有给定参数num,直接调用了函数,我们可以看到函数内部并没有声明局部的num,而是直接用num赋值,在这里要说一下,千万不要用这种万恶的写法,在工作中很容易给自己和他人造成意想不到的后果,然后num全局的值就被覆盖了。

总结

本文仅代表我个人结论,如果大家有不同的看法,非常愿意向大家学习。 最后说一下javascript的基本类型和引用类型:

  1. 基本类型 :Undefined / Null / Boolean / Number / String
  2. 引用类型 :Object / Array / Function / Date / RegExp / Error / Map / Set … .