最近我开始通过Nicholas C. Zakas'预订Web开发人员的专业JavaScript,我遇到了一些我自己无法解决的问题。
正如标题所说,这些都是关于JavaScript函数中的命名参数和参数对象。
E.g。我们有这段代码:
function doAdd(num1 , num2) {
arguments[1] = 10;
alert(arguments[0] + num2);
}
doAdd(10 , 20);
本书说,参数对象中的值会自动反映在相应的命名参数中,因此num2
会输入值为 20 的函数,然后通过{{ 1}}并且最终获得 10 的值。所有好的都清楚到这一点。然后它说
这种效果只有一种方式:更改命名参数不会导致参数中相应值的更改。
问题出现的地方。
我尝试修改这段代码以了解作者的说法,但我失败了。
E.g。
arguments[1]
此时function doAdd(num1 , num2) {
arguments[1] = 10;
num2 = 40;
alert(arguments[0] + arguments[1]);
}
doAdd(10 , 20);
再次输入值 20 的功能,通过num2
更改为 10 然后再次更改为 40 这次通过命名参数arguments[1]
。警报弹出 50 ,因为更改为命名的参数不会导致num2
中相应值的更改。为什么警报不会弹出 20 ?
答案 0 :(得分:6)
这是因为本书假定您使用strict mode。
如果您在严格模式下运行代码,那么在给出书中所写内容的情况下,您将获得您期望的行为。
function doAdd(num1 , num2) {
"use strict";
arguments[1] = 10;
num2 = 40;
alert(arguments[0] + arguments[1]);
}
doAdd(10 , 20); // this alerts 20, alerts 50 in nonstrict mode
一个鲜为人知的事实是严格模式的整个要点是避免这种动态范围(这就是为什么参数被固定,with
不被允许而eval
表现不同的原因)。除了清晰度增益外,这还可以大幅提升速度。
另见this:
对于严格模式函数,arguments对象的属性值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接。
这就是NCZ在上下文中的含义,引用了本书:
严格模式对如何使用参数对象进行了一些更改。首先,任务, 如上例所示,不再有效。尽管如此,num2的值仍未定义 参数[1]已被赋值为10.其次,尝试覆盖参数的值是a 语法错误。 (代码不会执行。) - 第82页,语言基础知识,专业JavaScript,Nicholas C. Zakas
答案 1 :(得分:1)
引自ECMA 5.1 Specifications for Arguments Object,
注1 对于非严格模式函数数组索引(在15.4中定义)命名数据属性的参数对象,其数字名称值小于相应函数对象的形式参数最初与函数执行上下文中相应的参数绑定共享它们的值。 这意味着更改属性会更改参数绑定的相应值,反之亦然。
它没有警告20,因为根据ECMA 5.1规范,在非严格模式函数中,使用数字键变换参数对象,也将更改与数字键对应的实际形式参数。
在您的情况下,当您更改arguments[1]
时,您也在更改第二个参数。同样,当您更改num2
时,您也在更改arguments[1]
。