简体   繁体   English

是否可以重写JavaScript的apply函数?

[英]Is it possible to rewrite JavaScript's apply function?

I've been rewriting a lot of JavaScript's higher-order functions to get the hang of functional programming, and I'm stuck on apply . 我一直在重写许多JavaScript的高阶函数,以掌握函数式编程的窍门,而我始终坚持apply Is it possible to write apply in JavaScript? 是否可以写apply在JavaScript? Assuming all other native functions are present, and that the ES5 spec is being used. 假设存在所有其他本机功能,并且正在使用ES5规范。

With ES5 and below, I don't think you can do it without using eval (see below). 对于ES5及以下版本,我认为不使用eval就无法做到(请参阅下文)。 You can almost do it with a massive switch statment on args.length , but at some point, you just have to say there's a limit to the number of cases in that switch . 几乎可以使用args.length上的大量开关语句来args.length ,但是在某些时候,您只需要说该switchcases数是有限的。

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!");
    }
};

If you're allowing eval , though, you can absolutely do it — full credit to blex for suggesting eval : 但是,如果您允许使用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);
};

Live Example: 现场示例:

 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> 

Or if you want to use Array#reduce : 或者,如果您想使用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);
};

You said ES5 in your question, but just for completeness: It's really easy in ES6 thanks to the spread operator ( ... ): 您在问题中说过ES5,但出于完整性考虑:由于使用了传播运算符( ... ),因此在ES6中确实非常容易:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM