2016-04-03 53 views
2

訪問到的論點我有兩個簡單的循環功能,其處理函數的參數:JS:奇怪的結果,而通過鑰匙

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 } 

爲什麼?

回答

2

for循環不是函數。因此,arguments保留getArgs的上下文。

forEach當你正在考慮它作爲一個循環,實際上是一個運行循環的函數。因此,arguments有一個新的上下文,這不是你所期望的。

要解決此問題,請將參數設置爲新變量並在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]}); 
    }); 
}; 
+0

你們都吹我的腦海裏。很好的問題和答案! – Observer

+0

謝謝,優秀的回答,很乾淨。 – srgg6701

1

至極arguments -object?你與兩個不同的雜耍arguments -objects。
這就像this關鍵字,上下文很重要!

看看這個:

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] 
     }); 
    }) 
} 

但只要你用的參數對象亂搞(並將它傳遞給一些功能,像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] 
     }); 
    } 
} 

如果你想傳遞參數,你應該先將它們複製到一個數組中。

for(var i = arguments.length, args = new Array(i); i--;) args[i] = arguments[i];  
//now you can do whatever you want to args. 

但這是什麼目的。這樣的動態參數長度幾乎不是一個好主意,如果你想傳遞一個列表,然後傳遞一個列表(又名Array或者類似那樣)

1

foreach不工作的原因是你接受了參數進入一個閉包,所以你從參數中被拿走了。

嘗試將一個console.log(參數)添加到foreach閉包中,並且您可以看到它發生了什麼。

我提供了一些有效的例子,它基於你的代碼。

var getArgs=function(){ 
 

 
    var keys = Object.keys(arguments); 
 
    var myargs = arguments; \t // Copy arguments object (not as reference) so we can keep it into the scope when the arguments are reading from a closure or callback. 
 
    
 
    console.log("var in method"); 
 
    
 
    for(var argKey in arguments){ 
 
     console.log({argKey:argKey, argument:arguments[argKey]}); 
 
    } 
 
    
 
    console.log("foreach method by key"); 
 
    keys.forEach(function(value, key) { 
 
    \t console.log({argKey:key, argument:myargs[key]}); 
 
    }); 
 
    
 
    // Because we don't have foreach method for objects we can slice it as an array 
 
    console.log("foreach method by argument array"); 
 
    Array.prototype.slice.call(arguments).forEach(function(value, key) { 
 
    \t console.log({argKey:key, argument:value}); 
 
    }); 
 

 
}; 
 

 
getArgs(5,3,2,11,15,7,-25);