2012-10-21 40 views
0

我是JavaScript新手,遇到了'apply'方法。 作爲一個練習,我試着爲所有函數創建一個包裝函數,就像下面的代碼片斷一樣。 1.爲什麼這不能按預期工作,以及2.如何爲所有函數創建包裝函數?apply()不能按預期工作

function funcWrapper(func){ 
    return func.apply(this, arguments); 
}; 

function sum(num1, num2){ 
    return num1 + num2; 
} 

funcWrapper(sum, 2, 3); 
// expected 5, but returns 
// function sum(num1, num2){ 
// return num1 + num2; 
// }2 
+1

有趣的是,我從來沒有意識到這樣做' + '將函數轉換成字符串的JavaScript,始終以飽滿的。驚喜。 –

回答

2

這是因爲funcWrapper中的參數對象爲[function sum(num1, num2){ return num1 + num2; }, 2, 3],第一個參數是您傳遞的函數。 arguments對象是您傳遞給該函數的所有參數。

解決方法是排除作爲對象的第一個參數。通常在JavaScript中,人們使用數組的切片方法。那麼你可能會問自己,arguments是一個對象,並沒有這種方法。但是我們可以採取以下解決方法:

var args = Array.prototype.slice.call(arguments, 1); 
return func.apply(this, args); 

在funcWrapper中。再次,你把它縮短了由第一線轉換成這樣:

var args = [].slice.call(arguments, 1); 
return func.apply(this, args); 

你也可以換行到這樣的功能:

function _slice(obj, start, end) { 
    return [].slice.call(obj, start, end); 
} 

而且使用這樣的:

var args = _slice(arguments, 1); 

請注意,在ES6中(未在瀏覽器中實現)通過使用rest parameters來解決此問題:

function funcWrapper(func, ...args){ 
    return func.apply(this, args); 
}; 

還有一兩件事,當你正在試圖包裝構造,確保你也繼承了原型過,或者你陷入同樣的​​陷阱,因爲這問題:jQuery logger plugin

1

給出全部arguments對象.apply,你也給功能。

您需要排除第一個參數。

function funcWrapper(func) { 
    var sliced = [].slice.call(arguments, 1); 
    return func.apply(this, sliced); 
} 

另一種解決辦法來做到這一點:

function funcWrapper(func) { 
    return func.call.apply(func, arguments); 
} 

但是,這會有點混亂。

1

因爲arguments包含[sum, 2, 3]

你可能會想這樣做,如果你知道要調用的函數接受2個參數:

return func.call(this, arguments[1], arguments[2]); 

如果你不知道參數的數目,大概是:

var args = []; 
for(var i = 1; i < arguments.length; i++) 
    args.push(arguments[i]); 
return func.apply(this, args); 
1

return func.apply(this, arguments);應該return func.apply(this, Array.prototype.slice.call(arguments, 1));

2

在這裏看到這個鏈接https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

「參數對象不是數組。它類似於一個數組,但除長度外沒有任何數組屬性。例如,它沒有pop方法。然而,它可以轉化爲一個真正的數組:」

var args = Array.prototype.slice.call(arguments); 

嘗試

function funcWrapper(func){ 
    var args = Array.prototype.slice.call(arguments, 1); // skip func parameter 
    return func.apply(this, args); 
};