1

我是 javascript 新手,遇到了“应用”方法。作为练习,我尝试为所有函数创建一个包装函数,如下面的代码片段。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
4

5 回答 5

4

这是因为 funcWrapper 中的 arguments 对象是[function sum(num1, num2){ return num1 + num2; }, 2, 3],第一个参数是你传递的函数。arguments对象是您传递给函数的所有参数。

解决方案是排除作为对象的第一个参数。通常在 javascript 中,人们使用数组的 slice 方法。那么你可能会问自己那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 参数来解决的:

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

还有一件事,当您尝试包装构造函数时,请确保您也继承原型,否则您会陷入与此问题相同的陷阱:jQuery logger plugin

于 2012-10-21T05:12:07.817 回答
2

在此处查看此链接https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments

“arguments 对象不是 Array。它类似于 Array,但除了长度之外没有任何 Array 属性。例如,它没有 pop 方法。但是它可以转换为真正的 Array:”

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);
};
于 2012-10-21T05:13:22.323 回答
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);
}

但这有点令人困惑。

于 2012-10-21T05:11:12.497 回答
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);
于 2012-10-21T05:12:08.073 回答
1

return func.apply(this, arguments);应该return func.apply(this, Array.prototype.slice.call( arguments, 1 ));

于 2012-10-21T05:12:57.240 回答