Javascript JS:通过键访问参数时出现奇怪的结果

Javascript JS:通过键访问参数时出现奇怪的结果,javascript,object,for-loop,foreach,arguments,Javascript,Object,For Loop,Foreach,Arguments,我有一个带有两个简单循环的函数,它们处理函数的参数: var getArgs=function(){ var keys = Object.keys(arguments); for(var argKey in arguments){ console.log({argKey:argKey, argument:arguments[argKey]}); } keys.forEach(function(argKey){ console.

我有一个带有两个简单循环的函数,它们处理函数的参数:

var getArgs=function(){

    var keys = Object.keys(arguments);

    for(var argKey in arguments){
        console.log({argKey:argKey, argument:arguments[argKey]});
    }

    keys.forEach(function(argKey){
        console.log({argKey:argKey, argument:arguments[argKey]});
    });
};
……及其呼吁:

getArgs(5,3,2,11,15,7,-25);
看起来它们做的是一样的,所以输出也应该是一样的,但事实并非如此。 第一种是可以预测的。输出为:

{ argKey: '0', argument: 5 }
{ argKey: '1', argument: 3 }
{ argKey: '2', argument: 2 }
{ argKey: '3', argument: 11 }
{ argKey: '4', argument: 15 }
{ argKey: '5', argument: 7 }
{ argKey: '6', argument: -25 }
但第二种情况表现得出乎意料:

{ argKey: '0', argument: '0' }
{ argKey: '1', argument: 1 }
{ argKey: '2', argument: [ '0', '1', '2', '3', '4', '5', '6' ] }
{ argKey: '3', argument: undefined }
{ argKey: '4', argument: undefined }
{ argKey: '5', argument: undefined }
{ argKey: '6', argument: undefined }

为什么?

for循环不是一个函数。因此,参数保留getArgs的上下文

当您将forEach视为一个循环时,它实际上是一个运行循环的函数。因此,参数有一个新的上下文,这不是您所期望的

要解决此问题,请将参数设置为新变量,并在forEach中使用该变量

运行此代码,您将获得预期结果:

var getArgs=function(){

    var keys = Object.keys(arguments);
    var args = arguments;

    for(var argKey in arguments){
        console.log({argKey:argKey, argument:arguments[argKey]});
    }

    keys.forEach(function(argKey){
        console.log({argKey:argKey, argument:args[argKey]});
    });
};
谁是反对者?你在处理两个完全不同的对象。 就像这个关键词,上下文很重要

看看这个:

var getArgs = function(){
    var keys = Object.keys(arguments);

    for(var argKey in arguments){
        console.log({argKey:argKey, argument:arguments[argKey]});
    }

    var _args = arguments;
    keys.forEach(function(argKey){  
        console.log({
            argKey: argKey,

            argument: arguments[argKey], 
            argumentFunction: arguments.callee.toString(),

            realArgument: _args[argKey],
            realArgumentFunction: _args.callee.toString()
        });
    })
}
//or that:
var getArgs = function(){
    var keys = Object.keys(arguments);
    keys.forEach((argKey) => {  
        console.log({
            argKey: argKey,
            argument: arguments[argKey]
        });
    })
}
但是,一旦你搞乱了arguments对象并将其传递给object.keys之类的函数,这个函数就不能再优化了

var getArgs = function(){
    //you don't need for..in, you are not iterating over an Object or a (huge) sparse Array
    for(var i=0, len=arguments.length; i<len; ++i){
        console.log({
            argKey:i, 
            argument:arguments[i]
        });
    }
}

但这样做的目的是什么。这样的动态参数长度很少是一个好主意,如果你想传递一个列表,然后传递一个列表,即数组或诸如此类的东西,foreach不起作用的原因是你被带到一个闭包中,所以你从参数中获取参数

尝试将console.logarguments添加到foreach闭包中,您可以看到它发生了什么

我提供了一些有效的示例,这些示例基于您的代码

var getArgs=函数{ var keys=Object.keysarguments; var myargs=arguments;//将arguments对象复制为非引用,以便在参数从闭包或回调读取时将其保留在作用域中。 方法中的console.logvar; 参数中的forvar argKey{ log{argKey:argKey,argument:arguments[argKey]}; } console.logforeach方法通过键; keys.forEachfunctionvalue,key{ log{argKey:key,参数:myargs[key]}; }; //因为我们没有对象的foreach方法,所以我们可以将其作为数组进行切片 console.logforeach方法的参数数组; Array.prototype.slice.callarguments.forEachfunctionvalue,键{ log{argKey:key,argument:value}; }; };
getArgs5,3,2,11,15,7,-25;你们两个都让我大吃一惊。伟大的问题和答案!
for(var i = arguments.length, args = new Array(i); i--; ) args[i] = arguments[i];       
//now you can do whatever you want to args.