[英]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
,但是在某些时候,您只需要说该switch
的cases
数是有限的。
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.