2

我在测试东西。并发现如果我没有提供参数,我将无法设置参数。使用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]

4

4 回答 4

1

在发布了一个非常错误的答案后,我查看了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');

请注意,规范中还有更多内容,我在这里和那里进行了简化,但这基本上是正在发生的事情。

于 2013-07-04T21:22:04.240 回答
1

我的理解是参数是动态的,其长度由提供给函数的参数/参数的数量设置。

在第一种情况下,您只提供了一个参数,因此参数的大小为 1,因此参数 [1] 应该超出范围,而在第二种情况下,您有长度为 2 的参数,因此您可以使用其索引更改任一参数值.

于 2013-07-04T21:19:39.670 回答
0

你想通过这个来达到什么目的?

如果您想要“动态参数” abc('a),并且abc('a', 'b')两者都有效,但第一个会将缺少的参数设置为默认值,则您必须检查参数长度和/或所有参数值。

假设如下:abc('a', null)给出,然后呢?- 取决于逻辑,可以是好的,也可以是坏的。

鉴于此,检查参数向量并不是更聪明,而是更神秘,并且具有if (b=='undefined') b='default'更直接和更好理解的东西。

于 2013-07-04T21:24:07.533 回答
0

TL;DR:根据 ECMA 规范不可能,因为arguments仅绑定到与提供的参数匹配的形式参数。建议仅参考arguments而不是更改它。

示例:http: //jsfiddle.net/MattLo/73WfA/2/


关于参数

非严格arguments对象是到FormalParameterList的双向映射对象,FormalParameterList是根据提供的参数数量生成的列表,这些参数映射到目标函数定义/表达式中的已定义参数。

当控件进入函数代码的执行上下文时,会创建一个参数对象,除非(如 10.5 中所指定)标识符参数作为标识符出现在函数的 FormalParameterList 中,或者作为包含在函数代码中的 VariableDeclaration 或 FunctionDeclaration 的标识符出现。ECMA 5.1 规范(截至 2014 年 3 月 26 日)

arguments变量/变量arguments

参数到变量的映射仅在调用方法时在内部存在。映射是不可变的,并且是在每个实例调用目标函数时创建的。use strict当标志在函数范围内可用时,两者之间的更新绑定也被禁用。arguments成为严格的参考,不再是更新参数的方法。

对于非严格模式函数,数组索引(在 15.4 中定义)命名的参数对象的数据属性,其数值名称值小于相应函数对象的形式参数的数量,最初与函数的相应参数绑定共享它们的值执行上下文。这意味着更改属性会更改参数绑定的相应值,反之亦然。如果此类属性被删除然后重新定义,或者如果该属性更改为访问器属性,则该对应关系将被破坏。对于严格模式函数,参数对象的属性值只是传递给函数的参数的副本,属性值和形参值之间没有动态链接。ECMA 5.1 规范(截至 2014 年 3 月 26 日)

怎么样length

arguments.length最初可以作为一个指标来确定满足了多少形式参数,但它是不安全的,因为arguments可以更改而无需length自动更新。length不会更新,因为它不是真正的数组,因此不符合Array规范。

于 2014-03-26T17:38:25.480 回答