是否无法使用arguments属性设置尚未提供的参数
Is it not possible to set arguments that have not been provided, using arguments property
我在测试一些东西。我发现,如果我没有提供论据,我就无法设置论据。使用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]
就无法连接。
我的理解是,参数是动态的,其长度由提供给函数的参数/参数的数量设置。
在第一种情况下,您只提供了一个参数,因此参数的大小为1,因此参数[1]应该超出范围,而在第二种情况中,您有长度为2的参数,因此您可以通过使用其索引来更改任何一个参数值。
在发布了一个非常错误的答案后,我查看了ECMA规范,代码中显示了当创建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');
请注意,规范中还有一些内容,我只是在这里和那里简单地介绍了一下,但这基本上就是正在发生的事情。
您试图通过此实现什么?
如果您希望像abc('a)
和abc('a', 'b')
这样的"动态参数"都有效,但第一个参数会将缺少的参数设置为默认值,则必须检查参数长度和/或所有参数值。
假设给出以下内容:abc('a', null)
,然后是什么?-取决于逻辑,可以是好的,也可以是坏的。
考虑到这一点,检查自变量向量并不是更聪明,而是更神秘,而且像if (b=='undefined') b='default'
这样的东西更直接、更容易理解。
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
标志在函数范围内可用时,也会禁用两者之间的更新绑定。CCD_ 17成为严格的参考,而不再是更新参数的方式。
对于非严格模式函数,参数对象的数组索引(在15.4中定义)命名的数据属性的数值名称值小于相应函数对象的形式参数的数量,最初与函数执行上下文中的相应参数绑定共享它们的值。这意味着更改属性会更改参数绑定的相应值,反之亦然。如果删除此类属性然后重新定义,或者将该属性更改为访问器属性,则会破坏这种对应关系。对于严格模式函数,arguments对象属性的值只是传递给函数的参数的副本,并且属性值和形式参数值之间没有动态链接ECMA 5.1规范(截至2014年3月26日)
length
呢
arguments.length
最初可以是确定满足多少形式参数的指标,但这是不安全的,因为arguments
可以在length
不自动更新的情况下更改。length
不更新,因为它不是真正的阵列,因此不符合Array
规范。
- 当我将参数设置为对象时,JavaScript返回TypeError
- jQuery UI 选项卡 - 将参数设置为下一个/上一个按钮单击
- 通过参数设置html组合框的选定选项
- 如何将查询参数设置为我的所有路线,当它改变时-在恩伯
- 根据先前的参数设置位置 $routeChangeError 使用角度 JS
- 角度中的组合框(选择组件)不基于参数设置显示值
- 在 ES6 中自动将参数设置为实例属性
- 基于 URL 参数设置 Javascript Cookie
- Nodejs 将命令行参数设置为常量
- 通过javaScript将参数设置为android webView
- MongoDB:使用空参数设置$unset给出409错误
- 使用动态参数设置onclick属性
- 无法将默认布尔参数设置为默认值
- 如何为XHR POST参数设置动态URL
- 如何在遍历对象时为setTimeout参数设置固定的时间偏移量
- 对函数使用.bind(),并将一些参数设置为常量,但不将其他参数设置为JavaScript
- 在Soundcloud Javascript SDK中,如何正确发送'过滤器'参数设置为'/曲目&
- 将查询字符串参数设置为输入值
- Sailsjs:基于请求参数设置响应方法
- Knockoutjs函数,用参数设置href url