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

How to implement Function.prototype.apply without using apply?

本文关键字:apply 情况下 Function prototype 实现      更新时间:2023-09-26
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 进行绑定的困扰。

我能想到的唯一方法是使用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]);

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

编辑:现在它适用于任何数据类型。

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

如果您使用的是 ES6,则需要点差运算符...

foo(...[1,3,5]); //equivalent to foo(1, 3, 5)
fn.bind(context, ...args);

否则,您可以在bind上拨打apply

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

fn作为fn.bind的上下文传递将保留其正常行为,并且您需要将要传递的所有参数组合到单个数组中,因此进行串联。

不知道为什么需要使用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));