我是javascript的新手,并且遇到了'apply'方法。 作为练习,我尝试为所有函数创建一个包装函数,如下面的代码片段。 1.为什么这不能按预期工作,以及2.如何为所有函数创建包装函数?
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
答案 0 :(得分:3)
这是因为funcWrapper中的arguments对象是[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 :(得分:2)
点击此链接https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments
“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);
};
答案 2 :(得分: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);
}
但这有点令人困惑。
答案 3 :(得分: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);
答案 4 :(得分:1)
return func.apply(this, arguments);
应为return func.apply(this, Array.prototype.slice.call( arguments, 1 ));