在引用原始函数的同时覆盖 JavaScript 函数
我有一个函数 a()
,我想重写它,但也让原始的 a()
根据上下文按顺序执行。 例如,有时当我生成页面时,我想像这样覆盖:
function a() {
new_code();
original_a();
}
有时像这样:
function a() {
original_a();
other_new_code();
}
How do I get that original_a()
from inside the overriding a ()? 有可能吗?
请不要建议以这种方式覆盖的替代方案,我知道很多。 我是专门问这个方法的。
I have a function, a()
, that I want to override, but also have the original a()
be performed in an order depending on the context. For example, sometimes when I'm generating a page I'll want to override like this:
function a() {
new_code();
original_a();
}
and sometimes like this:
function a() {
original_a();
other_new_code();
}
How do I get that original_a()
from within the over-riding a()
? Is it even possible?
Please don't suggest alternatives to over-riding in this way, I know of many. I'm asking about this way specifically.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
您可以这样做:
在匿名函数内声明
original_a
可以防止它扰乱全局命名空间,但它在内部函数中可用。就像 Nerdmaster 在评论中提到的那样,请务必在末尾包含
()
。 您想要调用外部函数并将结果(两个内部函数之一)存储在a
中,而不是将外部函数本身存储在a
中>。You could do something like this:
Declaring
original_a
inside an anonymous function keeps it from cluttering the global namespace, but it's available in the inner functions.Like Nerdmaster mentioned in the comments, be sure to include the
()
at the end. You want to call the outer function and store the result (one of the two inner functions) ina
, not store the outer function itself ina
.代理模式可能会帮助您:
The Proxy pattern might help you:
谢谢大家,代理模式真的很有帮助......实际上我想调用一个全局函数 foo..
在某些页面中我需要进行一些检查。 所以我做了以下事情。
谢谢这真的帮助了我
Thanks guys the proxy pattern really helped.....Actually I wanted to call a global function foo..
In certain pages i need do to some checks. So I did the following.
Thnx this really helped me out
您可以使用如下结构覆盖函数:
例如:
编辑:修复了拼写错误。
You can override a function using a construct like:
For example:
Edit: Fixed a typo.
传递任意参数:
Passing arbitrary arguments:
@Matthew Crumley 提供的答案是利用立即调用的函数表达式,将旧的“a”函数关闭到返回函数的执行上下文中。 我认为这是最好的答案,但就我个人而言,我更喜欢将函数“a”作为参数传递给 IIFE。 我认为这是更容易理解的。
The answer that @Matthew Crumley provides is making use of the immediately invoked function expressions, to close the older 'a' function into the execution context of the returned function. I think this was the best answer, but personally, I would prefer passing the function 'a' as an argument to IIFE. I think it is more understandable.
上面的示例没有正确应用
this
或将参数
正确传递给函数重写。 下划线_.wrap() 包装现有函数,应用this
并正确传递参数
。 请参阅:http://underscorejs.org/#wrapThe examples above don't correctly apply
this
or passarguments
correctly to the function override. Underscore _.wrap() wraps existing functions, appliesthis
and passesarguments
correctly. See: http://underscorejs.org/#wrap在我看来,最重要的答案不可读/不可维护,并且其他答案没有正确绑定上下文。 这是一个使用 ES6 语法来解决这两个问题的可读解决方案。
In my opinion the top answers are not readable/maintainable, and the other answers do not properly bind context. Here's a readable solution using ES6 syntax to solve both these problems.
我有一些其他人编写的代码,并且想向我在代码中找不到的函数添加一行。 因此,作为一种解决方法,我想覆盖它。
但没有一个解决方案对我有用。
以下是对我的案例有效的方法:
I had some code written by someone else and wanted to add a line to a function which i could not find in the code. So as a workaround I wanted to override it.
None of the solutions worked for me though.
Here is what worked in my case:
我为类似的场景创建了一个小助手,因为我经常需要覆盖多个库中的函数。 该助手接受“命名空间”(函数容器)、函数名称和重写函数。 它将用新函数替换引用的命名空间中的原始函数。
新函数接受原始函数作为第一个参数,原始函数参数作为其余参数。 它每次都会保留上下文。 它也支持 void 和非 void 函数。
例如 Bootstrap 的用法:
不过我没有创建任何性能测试。 它可能会增加一些不必要的开销,这可能会或不会是一个大问题,具体取决于场景。
I've created a small helper for a similar scenario because I often needed to override functions from several libraries. This helper accepts a "namespace" (the function container), the function name, and the overriding function. It will replace the original function in the referred namespace with the new one.
The new function accepts the original function as the first argument, and the original functions arguments as the rest. It will preserve the context everytime. It supports void and non-void functions as well.
Usage for example with Bootstrap:
I didn't create any performance tests though. It can possibly add some unwanted overhead which can or cannot be a big deal, depending on scenarios.
所以我的答案最终是一个允许我使用指向原始对象的 _this 变量的解决方案。
我创建了一个“Square”的新实例,但是我讨厌“Square”生成其大小的方式。 我认为它应该符合我的具体需求。 然而,为了做到这一点,我需要广场有一个更新的“GetSize”函数,该函数的内部调用广场中已经存在的其他函数,例如 this.height、this.GetVolume()。 但为了做到这一点,我需要在没有任何疯狂黑客的情况下做到这一点。 这是我的解决方案。
其他一些对象初始值设定项或辅助函数。
在另一个对象中函数。
So my answer ended up being a solution that allows me to use the _this variable pointing to the original object.
I create a new instance of a "Square" however I hated the way the "Square" generated it's size. I thought it should follow my specific needs. However in order to do so I needed the square to have an updated "GetSize" function with the internals of that function calling other functions already existing in the square such as this.height, this.GetVolume(). But in order to do so I needed to do this without any crazy hacks. So here is my solution.
Some other Object initializer or helper function.
Function in the other object.
不确定它是否适用于所有情况,但在我们的例子中,我们尝试重写 Jest 中的
describe
函数,以便我们可以解析名称并跳过整个describe 如果满足某些条件则阻止。
以下是对我们有用的方法:
这里有两件事至关重要:
我们不使用箭头函数
() =>
。箭头函数更改对
this
的引用,我们需要将其作为文件的this
。使用
this.describe
和this.describe.skip
而不仅仅是describe
和describe.skip
>.再次强调,不确定它对任何人都有价值,但我们最初试图摆脱 Matthew Crumley 的 很好的答案,但需要使我们的方法成为一个函数并接受参数以便在条件中解析它们。
Not sure if it'll work in all circumstances, but in our case, we were trying to override the
describe
function in Jest so that we can parse the name and skip the wholedescribe
block if it met some criteria.Here's what worked for us:
Two things that are critical here:
We don't use an arrow function
() =>
.Arrow functions change the reference to
this
and we need that to be the file'sthis
.The use of
this.describe
andthis.describe.skip
instead of justdescribe
anddescribe.skip
.Again, not sure it's of value to anybody but we originally tried to get away with Matthew Crumley's excellent answer but needed to make our method a function and accept params in order to parse them in the conditional.