图片描述

这本红宝书相信大家很熟悉,甚至比我读过的次数要多,不过今天在阅读函数传参部分章节时,发现了书中一个可以算是小错误的知识点。

我们知道,arguments作为一个类数组,和函数的传参是一一对应的,那么如果改变其中一个的值,会对另一个有什么影响呢?

在红宝书第66页第一段,作者给予了论述:

   function doAdd(num1,num2){
    arguments[1]=10;
    alert(arguments[0]+num2)
   }

“每次执行这个doAdd()函数都会重写第二个参数,将第二个参数的值修改为10。因为arguments对象中的值会自动反映到对应的命名参数,所以修改arguments[1],也就修改了num2,结果它们的值都会变成10。不过,这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但它们的值会同步。但这种影响是单向的:修改命名参数不会改变argument中对应的值

这段解读非常深刻,于是我赶快打开编辑器进行尝试。我是这样做的:

function add1(num1,num2){
    arguments[1]=10;
    alert(num1+num2);
}
function add2(num1,num2){
    num2=10;
    alert(arguments[0]+arguments[1]);
}
add1(20,5);
add2(3,5);
add1(20);

这两个函数,分别对arguments[1]和其对应的传参num2做出修改,并弹出结果。在第一个函数中,因为给arguments[1]赋值这个动作将num2的值强行替换为10,所以在调用add1(20,5)时,我们得到的是num1+num2=20+10=30。这和书中论述无异。
然而在第二个函数add2中,将num2强行赋值为10,输出arguments[0]+arguments[1],按照作者以上的论述(斜体字部分),argument里的值应该保持不变,结果应该为3+5=8才对。但是浏览器结果最后给出的结果为13(3+10),在火狐、谷歌和IE下结果一致。这说明,改变传参的值,同样可以反过来改变对应arguments的值,两者的改变是相通的。

另外,如果只给add1传入一个参数,浏览器最后给出的结果为NaN,这说明:如果只传了一个值,那么为arguments[1]设置的值不会反应到命名参数中去,因为arguments对象的长度是由传入的参数个数决定的。此时num2的值始终为undefined,因此才会有输出NaN这一结果。


CatherineYF
167 声望3 粉丝