要理解函数的传参机制,首先,我们首先就要弄清楚的就是js数据类型的存储机制和变量复制的方式,上文中:js中为什么不能为值类型的变量动态添加属性呢?这里已经讨论过了,这里不再累赘,接着我们来讨论下,js的变量复制
请看以下代码:
<script type="text/javascript"> var int1 = 7; var int2 = int1; console.log(int1+"\n"+int2); /*输出 * *7 *7 */ </script>
在看:
<script type="text/javascript"> var object1 = new Object(); var object2 = object1; object1.name ="xiaobai"; console.log(object1.name+"\n"+object2.name); /*输出 * *xiaobai *xiaobai */ </script>
从上面代码的输出结果,我们可以看出,对于基本类型来说,其复制的是被复制变量在栈中的值,即创建了一个副本,对其中任何一个变量的改变都不会影响另外一个变量;对于引用类型来说,其复制的是被复制变量在栈中的值,但是这个值所存储的是变量指向到堆中的对象的指针,即该对象所存储的地址,复制后的变量虽然也是一个副本,但是却指向了与被复制的变量的同一个在堆中的对象。对其中任何一个变量所做的改变都会影响都会影响另外一个变量。
现在我们来看看,函数的传参,js中所有函数的参数都是按值来传递的
下面我们来看看下面这些代码:
<script type="text/javascript"> function addNum(num){ num +=10; return num; } var num1 =30; var result = addNum(num1); console.log(num1+"\n"+result); /* *输出: *30 *40 */ </script>
再看看下面的代码:
<script type="text/javascript"> function setName(obj){ obj.name = "xiaobai"; } var dog = new Object(); setName(dog); console.log(dog.name); /*输出 *xiaobai */ </script>
实际上我们看到,这种传参实际上做的就是把变量的值复制给函数内部的临时变量(这个临时变量其实也有一个专门指向他们的数组,就是我们常用于模仿重载的arguments数组),所不同的就是对于基础数据类型来说,他复制的就是传人参数在栈中的值,而引用类型复制的是参数在栈中的值,而这个值保存的是一个指向堆中地址的指针。
<script type="text/javascript"> function setName(obj){ obj.name = "xiaobai"; obj = new Object(); obj.name = "xiaohei"; } var dog = new Object(); setName(dog); console.log(dog.name); /*输出 *xiaobai */ </script>
在上面的黄色的代码中我们创建了另外一个对象,我们对他所做的任何的改变都不会影响带另外一个对象,因为它与参数所指向的对象是完成不同的对象。