包装函数和 function.length
假设我有以下代码,
/*...*/
var _fun = fun;
fun = function() {
/*...*/
_fun.apply(this, arguments);
}
我刚刚丢失了 _fun
上的 .length
数据,因为我试图用一些拦截逻辑来包装它。
以下内容不起作用
var f = function(a,b) { };
console.log(f.length); // 2
f.length = 4;
console.log(f.length); // 2
带注释的 ES5.1 规范声明 。 length
定义如下
Object.defineProperty(fun, "length", {
value: /*...*/,
writable: false,
configurable: false,
enumerable: false
}
鉴于 fun
内部的逻辑要求 .length
准确,如何在不破坏 的情况下拦截并覆盖这个函数.length
数据?
我有一种感觉,我需要使用 eval
和狡猾的 Function.prototype.toString
来构造一个具有相同数量参数的新字符串。我想避免这种情况。
Let's consider I have the following code
/*...*/
var _fun = fun;
fun = function() {
/*...*/
_fun.apply(this, arguments);
}
I have just lost the .length
data on _fun
because I tried to wrap it with some interception logic.
The following doesn't work
var f = function(a,b) { };
console.log(f.length); // 2
f.length = 4;
console.log(f.length); // 2
The annotated ES5.1 specification states that .length
is defined as follows
Object.defineProperty(fun, "length", {
value: /*...*/,
writable: false,
configurable: false,
enumerable: false
}
Given that the logic inside fun
requires .length
to be accurate, how can I intercept and overwrite this function without destroying the .length
data?
I have a feeling I will need to use eval
and the dodgy Function.prototype.toString
to construct a new string with the same number of arguments. I want to avoid this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我知道您更喜欢其他方式,但我能想到的就是将一些东西与
Function
构造函数组合在一起。至少可以说很混乱,但它似乎有效:I know you'd prefer some other way, but all I can think of is to hack together something with the
Function
constructor. Messy, to say the least, but it seems to work:正确且一致地伪造长度是 javascript 的最终前沿,这几乎是它的开始和结束。在一种几乎可以伪造一切的语言中,长度仍然有些神奇。 ES6 将会交付,我们现在可以根据您使用的引擎和版本来或多或少地伪造它。对于一般的 Web 兼容性来说,这还有很长的路要走。 Proxies/noSuchMethod 在 Mozilla 中已经有一段时间了。代理和 WeakMap 已在 Chromium 和 Node 的 V8 中可用(需要启用标志),它们提供了正确伪造长度所需的工具。
关于“长度”的详细信息: http ://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
最终解决方案:http://wiki.ecmascript.org/doku.php?id=harmony:proxies + http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps
Faking length correctly and consistently is the final frontier in javascript and that's pretty much the beginning and end of it. In a language where you can fake just about everything, length is still somewhat magical. ES6 will deliver, and we can fake it now to greater and lesser degrees depending which engine and version you're in. For general web compatability it's a ways off. Proxies/noSuchMethod has been in Mozilla for a while. Proxies and WeakMaps have gotten to usable in V8 in Chromium and and node (requiring flags to enable) which provide the tool you need to fake length correctly.
In detail on "length": http://perfectionkills.com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array/
The eventual solution: http://wiki.ecmascript.org/doku.php?id=harmony:proxies + http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps
我为此目的使用以下函数;对于具有合理参数数量的函数来说,它确实很快,比公认的答案更灵活,并且适用于具有超过 26 个参数的函数。
I use the following function for this purpose; it’s really fast for functions with reasonable parameter counts, more flexible than the accepted answer and works for functions with more than 26 parameters.
如果您需要支持具有任意数量参数的函数,则只需沿着
eval
/Function
路线进行即可。如果您可以设置合理的上限(我的示例是 5),那么您可以执行以下操作:这种包装代码的方法也可以通过创建不同的
where
开关进行扩展。我实现了before
和after
因为它们对我自己的项目最有用,而around
只是因为它让我想起了 lisp。使用此设置,您还可以将包装 (var f
) 交给外部代码,从而允许您为where
关键字开发类似系统的插件,这意味着您可以轻松地扩展或覆盖wrapFunction
支持的内容。显然,您可以根据需要更改代码的实际包装方式,关键实际上只是使用与 999 和 AdrianLang 类似的技术,而不必担心构建字符串并传递给
new Function
。You only need to go down the
eval
/Function
route if you need to support functions with any number of parameters. If you can set a reasonable upper limit (my example is 5) then you can do the following:This method of wrapping code is also extendable by creating different
where
switches. I've implementedbefore
andafter
because they are the most useful for my own project — andaround
just because it reminds me of lisp. Using this set-up you could also hand off the wrapping (var f
) to external code allowing you to develop a plugin like system forwhere
keywords, meaning that you could easily extend or override whatwrapFunction
supported.Obviously you can change how the code is actually wrapped however you like, the key really is just using a similar technique to 999 and AdrianLang, just without worrying about building strings and passing to
new Function
.