是否可以重写JavaScript的应用功能?

时间:2015-06-25 13:32:37

标签: javascript functional-programming override

我已经重写了许多JavaScript的高阶函数来解决函数式编程的问题,而且我一直坚持apply。是否可以在JavaScript中编写apply?假设存在所有其他本机函数,并且正在使用ES5规范。

1 个答案:

答案 0 :(得分:5)

使用ES5及以下版本,如果不使用eval,我认为你无法做到(见下文)。您可以 使用args.length上的大量切换声明执行此操作,但在某些时候,您只需要说cases的数量有限制。 1}}在switch

Function.prototype.newApply = function(thisArg, args) {
    switch (args.length) {
        case 0: return this.call(thisArg);
        case 1: return this.call(thisArg, args[0]);
        case 2: return this.call(thisArg, args[0], args[1]);
        // etc..
        default: throw new Error("She canna tek any more!");
    }
};

如果你允许eval,你绝对可以这样做 - 完全归功blex建议eval

Function.prototype.newApply = function(thisArg, args) {
    var f = this,
        call = "f.call(thisArg",
        i;
    for (i = 1; i < args.length; ++i) {
        call += ", args[" + i + "]";
    }
    call += ")";
    return eval(call);
};

直播示例:

Function.prototype.newApply = function(thisArg, args) {
  var f = this,
      call = "f.call(thisArg",
      i;
  for (i = 0; i < args.length; ++i) {
    call += ", args[" + i + "]";
  }
  call += ")";
  return eval(call);
};

var obj1 = {
  foo: "foo",
  bar: "bar"
};
var obj2 = {
  foo: "F",
  bar: "B"
};
function caps(o1, o2) {
  var k;
  snippet.log("this.x = " + this.x);
  for (k in o1) {
    o1[k] = o1[k].toUpperCase();
  }
  for (k in o2) {
    o2[k] = o2[k].toLowerCase();
  }
}

caps.newApply({x:42}, [obj1, obj2]);
snippet.log(JSON.stringify(obj1));
snippet.log(JSON.stringify(obj2));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

或者如果您想使用Array#reduce

Function.prototype.newApply = function(thisArg, args) {
    var f = this,
        call = args.reduce(function(acc, _, index) {
            return acc + ", args[" + index + "]";
        }, "f.call(thisArg") + ")";
    return eval(call);
};

你在问题​​中说过ES5,但仅仅是为了完整性:感谢扩展运算符(...)在ES6中非常容易:

Function.prototype.newApply = function(thisArg, args) {
    return this.call(thisArg, ...args);
};