也许你们对于函数的参数都不会太在乎,简单来讲,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另外一个变量同样。深刻研究,你会发现其实没那么简单,这个传参是要分俩种状况(其实这是个错误的说法,ECMAScript中全部函数的参数都是按值传递的——《高程3》原话,之因此这里说俩种,是由于结合引用传参更容易理解)—— 值传参和引用传参。 html
值传参针对基本类型,引用传参针对引用类型,传参能够理解为复制变量值。基本类型复制后俩个变量彻底独立,以后任何一方改变都不会影响另外一方;引用类型复制的是引用(即指针),以后的任何一方改变都会映射到另外一方。函数
很多人对参数都是按值传递的感到困惑,由于访问变量有按值和按引用两种方式。下面就来看看有何不一样:spa
这一段很重要:咱们能够把ECMAScript函数的参数想象成局部变量。在向参数传递基本类型的值时,被传递的值被复制给一个局部变量(即命名参数,或者用ECMAScript的概念来讲,就是arguments对象中的一个元素)。在向参数传递引用类型时,会把这个值在内存中的地址(指针)复制给一个局部变量,所以这个局部变量的变化会反映在函数的外部。指针
1 function addTen(num) { 2 num += 10; 3 return num; 4 } 5 6 var count = 20; 7 var result = addTen(count); //按值传递 num = count 8 alert(count); // 20, 没变化 9 alert(result); // 30
很好理解,由于是按值传递的,传递完后俩个变量各不相干!code
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 } 4 5 var person = new Object(); 6 setName(person); // obj = person 7 alert(person.name); // "Nicholas" 看起来是按引用传递,但千万不要觉得是按引用传递~~~
当 var person = new Object(); 时,能够用下图表示变量和对象的关系:htm
当调用函数 setName(person); 时,下图能够表示全局变量person和局部变量obj的关心:对象
以上代码中建立一个对象,并将其保存在变量person中。而后,这个变量被传递到setName(obj)函数中以后就被复制给了obj。在这个函数内部,obj和person引用的是同一个对象。换句话说,即便ECMAScript说这个变量是按值传递的,但obj也会按引用来访问同一个对象。因而,在函数内部为obj添加name属性后,函数外部的person也将有所反应;由于这时的person和obj指向同一个堆内存地址。因此,不少人错误的认为:在局部做用域中修改的对象会在全局对象中反映出来,就说明参数是按引用传递的。blog
为了证实对象也是按值传递的,咱们再来看看下面这个通过修改的例子:ip
1 function setName(obj) { 2 obj.name = "Nicholas"; 3 obj = new Object(); //改变obj的指向,此时obj指向一个新的内存地址,再也不和person指向同一个 4 obj.name = "Greg"; 5 } 6 7 var person = new Object(); 8 setName(person); //你看看下面,相信我也是按值传递的了吧 9 alert(person.name); //"Nicholas"
当建立obj对象 obj = new Object(); 时,来看看这时person和obj的关系图:内存
这个例子与前一个惟一的区别,就是setName()函数中添加了两行代码: obj = new Object(); 用来改变obj的指向; obj.name = "Greg"; 用来给新建立的obj添加属性。若是是按引用传递的,那么person就会自动被修改成指向新建立的obj的内存地址,则person的name属性值被修改成"Greg"(这句话以前说的有误,引用传递的是指针的值,obj=new Object()改写了本身的指向,并不会影响到person的指向,这种方式就是按引用传递。即便不把对象赋值给函数的参数,obj改写指向对person也没影响,见下面代码)。可是,当访问person.name时,显示的结果为"Nicholas"。这说明即便在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后被当即销毁!
推翻以上都是按值传递的结论:
var person=new Object(); var obj = person; // 赋值 obj.name="ABC"; obj=new Object(); obj.name="BCD"; console.log(person.name);// ABC 并无影响person的指向
综上所述,仍是以为参数传递对象时是按引用传递的,欢迎指正!