我在测试东西。并发现如果我没有提供它,我无法设置参数。
使用arguments[1]
等
示例:
function abc (a,b) {
arguments[1] = 'new value';
console.log(b);
}
abc('a');
它无效。
我知道我可以像if (b=='undefined') b='default';
那样设定值,但为什么我不喜欢这样。换句话说,这种行为是出乎意料的,不是吗?
另一方面,如果你提供参数,它会被改变!
这样调用函数会输出新值
abc('a','b');
是否有解决方案,如果您想使用arguments[2]
设置值并在调用函数时传递参数。
经过更多测试后,似乎b
如果没有被调用,则无法与arguments[1]
建立关联。
答案 0 :(得分:1)
我的理解是参数是动态的,其长度由提供给函数的参数/参数的数量来设定。
在第一种情况下,您只提供了一个参数,因此参数的大小为1,因此参数[1]应该超出范围,而在第二种情况下,您有长度为2的参数,因此您可以更改任一参数值使用它的索引。
答案 1 :(得分:1)
在发布了一个非常错误的答案后,我看了ECMA Spec,这里是代码,当arguments
对象被创建时,JavaScript会做什么:
function abc () {
var names = ["a", "b"]; //as normally provided in the function declaration: function (a, b)
var a, b;
var args = {};
var mappedNames = [];
args.length = arguments.length;
var index = args.length - 1;
//this is the crucial part. This loop adds properties to the arguments object
//and creates getter and setter functions to bind the arguments properties to the local variables
//BUT: the loop only runs for the arguments that are actually passed.
while (index >= 0) {
var val = arguments[index];
if (index < names.length) {
var name = names[index];
if (mappedNames.indexOf(name) === -1) {
mappedNames.push(name);
var g = MakeArgGetter(name);
var p = MakeArgSetter(name);
Object.defineProperty(args, index.toString(), {get : g, set : p, configurable : true});
}
}
args[index.toString()] = val;
index--;
}
function MakeArgGetter(name) {
return function zz(){
return eval(name);
};
}
function MakeArgSetter(name) {
return function tt(value) {
eval(name + " = value;");
};
}
console.log(args[0]); //ab
args[0] = "hello";
args[1] = "hello";
console.log(a); //hello
console.log(b); //undefined
}
abc('ab');
请注意,Spec中还有更多内容,我在这里和那里简单地说它,但这基本上就是发生了什么。
答案 2 :(得分:0)
你想通过这个来实现什么目标?
如果你想让abc('a)
和abc('a', 'b')
这样的“动态参数”都有效,但是第一个将缺少的参数设置为默认值,你要么必须检查参数长度和/或所有参数值。
假设有以下内容:abc('a', null)
,那么呢? - 取决于逻辑,可以是好的但也可能是坏的。
鉴于此,检查参数向量并不聪明,但更加神秘,并且if (b=='undefined') b='default'
更加直观,更易于理解。
答案 3 :(得分:0)
TL; DR:每个ECMA规范都不可能,因为arguments
只绑定到与提供的参数匹配的形式参数。建议仅引用arguments
而不是改变它。
示例:http://jsfiddle.net/MattLo/73WfA/2/
非严格arguments
对象是 FormalParameterList 的双向映射对象,它是根据提供的参数数量生成的列表,这些参数映射到目标函数中定义的参数确定指标/表达。
当控制进入功能代码的执行上下文时,除非(如10.5中所指定)标识符参数作为函数的FormalParameterList中的标识符出现或作为函数中包含的VariableDeclaration或FunctionDeclaration的标识符出现,否则创建自变量对象。码。 ECMA 5.1规范(截至2014年3月26日)
arguments
变量/变量到arguments
当调用方法时,仅在内部存在参数到变量的映射。映射是不可变的,并且在每个实例调用目标函数时创建。当use strict
标志在函数范围内可用时,也会禁用两者之间的更新绑定。 arguments
严格地成为参考,不再是更新参数的方法。
对于非严格模式函数,数组索引(在15.4中定义)命名数据属性的参数对象,其数字名称值小于相应函数对象的形式参数的数量,最初与相应的参数绑定共享它们的值在函数的执行上下文中。这意味着更改属性会更改参数绑定的相应值,反之亦然。如果删除并重新定义此属性或将属性更改为存取属性,则此对应关系将被破坏。对于严格模式函数,arguments对象的属性值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接。 ECMA 5.1规范(截至2014年3月26日)
length
怎么样? arguments.length
最初可以作为一个指标,用于确定满足多少正式参数,但由于arguments
可以在length
没有自动更新的情况下进行更改,因此不安全。 length
无法更新,因为它不是真正的数组,因此不会遵守Array
规范。