如何在不使用apply的情况下实现Function.prototype.apply?

时间:2015-12-19 00:41:02

标签: javascript

function sumArguments () {
  var value = this instanceof Number ? this : 0;
  for (var i = 0; i < arguments.length; i++) {
    value += arguments[i];
  }
  return value;
}

Function.prototype.apply1 = function() {
  var fn = this;
  var args = Array.prototype.slice.call(arguments);
  var context = args.shift();
  var newArgs = args[0];

  var boundfn = fn.bind(context, newArgs);

  return boundfn();
}

console.log(sumArguments.apply1(4, [1, 2, 3])); --> should equal 10

如何在不使用申请的情况下实施申请?我不知道如何将[1,2,3]的数组转换成1,2,3来传递给绑定。

3 个答案:

答案 0 :(得分:1)

我能想到的唯一方法就是使用eval

function apply(fn, args){
  var stringArgs = args.reduce(function(acc, el, i){
    var argString = 'args[' + i + ']';
    return acc += i === 0 ? argString : ',' + argString; 
  });
  return eval('fn(' + stringArgs + ')');
}
       
function test(first, second, third){
    console.log(first, second, third);
}

apply(test, [1, 2, 3]);

虽然,我无法理解为什么你需要这个。这也不适用于许多数据类型,如对象或字符串。它确实适用于数字。

修改:现在适用于任何数据类型。

答案 1 :(得分:1)

您的目标是使用上下文和提供的参数调用fn.bind,对吗?

如果您正在使用ES6,则展开运算符...就是您想要的:

foo(...[1,3,5]); //equivalent to foo(1, 3, 5)

fn.bind(context, ...args);

否则,您可以在apply上致电bind

fn.bind.apply(fn, [context].concat(args));

fn作为fn.bind的上下文传递将保留其正常行为,并且您需要将要传递的所有参数组合到一个数组中,从而进行连接。 / p>

答案 2 :(得分:0)

不确定为什么你需要使用apply,但是这里是sum函数来给你你想要的东西。它应该能够处理许多内部数组并忽略对象。

function sumArguments() {
    var value = this instanceof Number ? this : 0;
    for (var i = 0; i < arguments.length; i++) {
        if (typeof arguments[i] === 'number') {
            value += arguments[i];
        } else if (typeof arguments[i] === 'object' &&
                   typeof arguments[i].length !== 'undefined') {
            for (var j = 0; j < arguments[i].length; j++) {
                if (typeof arguments[i][j] === 'number') {
                    value += arguments[i][j];
                } else if (typeof arguments[i][j] === 'object' &&
                           typeof arguments[i][j].length !== 'undefined') {
                    value += sumArguments(arguments[i][j]);
                }
            }
        }
    }
    return value;
}

console.log(sumArguments(4, [1, 2, 3, [7, 8]], 5, 'a', 2));