你可以在声明后更改 Javascript 函数吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2136522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:54:14  来源:igfitidea点击:

Can you alter a Javascript function after declaring it?

javascriptfunctionoop

提问by pr1001

Let's say I have var a = function() { return 1; }. Is it possible to alter aso that a()returns 2? Perhaps by editing a property of the aobject, since every function is an object?

假设我有var a = function() { return 1; }。是否可以更改a以便a()返回2?也许通过编辑a对象的属性,因为每个函数都是一个对象

Update:Wow, thanks for all the responses. However, I'm afraid I wasn't looking to simply reassign a variable but actually edit an existing function. I am thinking along the lines of how you can combine partial functionsin Scala to create a new PartialFunction. I am interested in writing something similar in Javascript and was thinking that the existing function could perhaps be updated, rather than creating an entirely new Functionobject.

更新:哇,谢谢大家的回复。但是,恐怕我不想简单地重新分配变量,而是实际编辑现有函数。我正在思考如何在 Scala 中组合部分函数来创建一个新的PartialFunction. 我有兴趣在 Javascript 中编写类似的东西,并认为现有的函数可能会被更新,而不是创建一个全新的Function对象。

回答by jvenema

You can do all kinds of fun stuff with javascript, including redefining functions:

你可以用 javascript 做各种有趣的事情,包括重新定义函数:

var a = function(){ return 1; }

alert(a()); //1

// keep a reference
var old = a;

// redefine
a = function(){
  // call the original function with any arguments specified, storing the result
  var originalResult = old.apply(old, arguments);
  // add one
  return originalResult + 1;
};
alert(a()); //2

Voila.

瞧。

Edit: Updated to show this in a crazier scenario:

编辑:更新以在更疯狂的场景中显示:

var test = new String("123");
console.log(test.toString()); // logs 123
console.log(test.substring(0)); // logs 123
String.prototype.substring = function(){ return "hahanope"; }
console.log(test.substring(0)); // logs hahanope

You can see here that even though "test" is defined first, and we redefine substring() afterwards, the change still applies.

您可以在这里看到,即使首先定义了“test”,然后我们重新定义了 substring(),但更改仍然适用。

Side note: you really should reconsider your architecture if you're doing this...you're going to confuse the crap out of some poor developer 5 years down the road when s/he's looking at a function definition that's supposed to return 1, but seems to always return 2....

旁注:如果你这样做,你真的应该重新考虑你的架构......当他/她正在查看一个应该返回 1 的函数定义时,你会在 5 年后混淆一些可怜的开发人员的废话,但似乎总是返回 2....

回答by hmundt

I used something like this to modify an existing function whose declaration was not accessible to me:

我用这样的东西来修改一个现有的函数,它的声明对我来说是不可访问的:

// declare function foo
var foo = function (a) { alert(a); };

// modify function foo
foo = new Function (
  "a",
  foo.toSource()
    .replace("alert(a)", "alert('function modified - ' + a)")
    .replace(/^function[^{]+{/i,"")  // remove everything up to and including the first curly bracket
    .replace(/}[^}]*$/i, "")  // remove last curly bracket and everything after<br>
);

Instead of toSource() you could probably use toString()to get a string containing the function's declaration. Some calls to replace() to prepare the string for use with the Function Constructor and to modify the function's source.

您可以使用toString()来获取包含函数声明的字符串,而不是 toSource() 。一些对 replace() 的调用以准备与函数构造函数一起使用的字符串并修改函数的源代码。

回答by hashchange

So you want to modify the code of a function directly, in place, and not just reassign a different function to an existing variable.

因此,您希望直接就地修改函数的代码,而不仅仅是将不同的函数重新分配给现有变量。

I hate to say it, but as far as I have been able to figure it out - and I have tried -, it can't be done. True, a function is an object, and as such it has methods and properties which can be tweaked and overwritten on the object itself. Unfortunately, the function body is not one of them. It is not assigned to a public property.

我不想这么说,但据我所知——而且我已经尝试过了——这是不可能的。诚然,函数是一个对象,因此它具有可以在对象本身上进行调整和覆盖的方法和属性。不幸的是,函数体不是其中之一。它没有分配给公共财产。

The documentation on MDNlists the properties and methods of the function object. None of them gives us the opportunity to manipulate the function body from the outside.

MDN 上文档列出了函数对象的属性和方法。它们都没有给我们机会从外部操纵函数体。

That's because according to the spec, the function body is stored in the internal [[Code]]property of the function object, which can't be accessed directly.

那是因为根据规范,函数体存储在[[Code]]函数对象的内部属性中,不能直接访问。

回答by Sam Hasler

var a = function() { return 1; }
alert(a()) // 1
a = function() { return 2; }
alert(a()) // 2

technically, you're losing one function definition and replacing it with another.

从技术上讲,您正在丢失一个函数定义并用另一个替换它。

回答by jpsimons

How about this, without having to redefine the function:

这个怎么样,不用重新定义函数:

var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2

回答by rplantiko

I am sticking to jvenema's solution, in which I don't like the global variable "old". It seems better to keep the old function inside of the new one:

我坚持使用 jvenema 的解决方案,其中我不喜欢全局变量“old”。将旧函数保留在新函数中似乎更好:

function a() { return 1; }

// redefine
a = (function(){
  var _a = a;
  return function() {
  // You may reuse the original function ...
  // Typical case: Conditionally use old/new behaviour
    var originalResult = _a.apply(this, arguments);
  // ... and modify the logic in any way
    return originalResult + 1;
    }
})();
a()  // --> gives 2

回答by Peter Seliger

All feasible solutions stick to a "function wrapping approach". The most reliable amongst them seems to be the one of rplantiko.

所有可行的解决方案都坚持“函数包装方法”。 他们当中最可靠的,似乎是rplantiko之一

Such function wrapping easily can be abstracted away. The concept / pattern itself might be called "Method Modification". Its implementation definitely belongs to Function.prototype. It would be nice to be backed one day by standard prototypal method modifiers like before, after, around, afterThrowingand afterFinally.

这种函数包装很容易被抽象掉。概念/模式本身可能被称为“方法修改”。它的实现绝对属于Function.prototype. 这将是很好的标准原型方法修饰符等支持1天beforeafteraroundafterThrowingafterFinally

As for the aforementioned example by rplantiko ...

至于前面提到的 rplantiko 的例子......

function a () { return 1; }

// redefine
a = (function () {
  var _a = a;
  return function () {
    // You may reuse the original function ...
    // Typical case: Conditionally use old/new behaviour
    var originalResult = _a.apply(this, arguments);
    // ... and modify the logic in any way
    return originalResult + 1;
  };
})();

a(); // --> gives 2

... and making use of [around], the code would transform to ...

...并利用[around],代码将转换为 ...

function a () { return 1; }

console.log("a : ", a);
console.log("a() : ", a());


a = a.around(function (proceed, interceptor, args) {
  return (proceed() + 1);
});

console.log("a : ", a);
console.log("a() : ", a());

回答by Pocho La Pantera

This is a Clear Examplebased on a control timepicker eworld.uiwww.eworldui.net

这是一个基于控件时间 选择器的清晰示例eworld.uiwww.eworldui.net

Having a TimePicker eworld.uiwhere JavaScript is unreachable from outside, you can't find any js related to those controls. So how can you add a onchange event to the timepicker ?

拥有一个eworld.ui无法从外部访问 JavaScript的 TimePicker ,您无法找到与这些控件相关的任何 js。那么如何将 onchange 事件添加到 timepicker 呢?

There is a jsfunction called when you Selecta time between all the options that the control offer you. This function is: TimePicker_Up_SelectTime

js当您Select在控件为您提供的所有选项之间间隔一段时间时,会调用一个函数。这个函数是: TimePicker_Up_SelectTime

First you have to copy the code inside this function.

首先,您必须复制此函数中的代码。

Evaluate...quikwatch...TimePicker_Up_SelectTime.toString()

评估...quikwatch...TimePicker_Up_SelectTime.toString()

function TimePicker_Up_SelectTime(tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if(lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if(enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if(customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");
}

Now

现在

Using the code that you have saved before reassign the same source code but add whatever you want..

使用您在重新分配相同的源代码之前保存的代码,但添加您想要的任何内容..

TimePicker_Up_SelectTime = function (tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if (lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if (enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if (customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");

    >>>>>>>  My function  >>>>>   RaiseChange(tbName);
}

I've added My Function to the function so now I can simulate an onchange event when I select a time.

我已经将我的函数添加到函数中,所以现在我可以在选择时间时模拟 onchange 事件。

RaiseChange(...) could be whatever you want.

RaiseChange(...) 可以是你想要的任何东西。

回答by Jon Onstott

If you're debugging javascript and want to see how changes to the code affects the page, you can use this Firefox extension to view/alter javascripts:

如果您正在调试 javascript 并想查看代码更改如何影响页面,您可以使用此 Firefox 扩展来查看/更改 javascripts:

Execute JS firefox extension: https://addons.mozilla.org/en-US/firefox/addon/1729

执行 JS firefox 扩展:https: //addons.mozilla.org/en-US/firefox/addon/1729

回答by morteza ataiy

You can change functions like other objects

您可以像其他对象一样更改功能

var a1 = function(){return 1;}
var b1 = a1;
a1 = function(){
  return b1() + 1;
};
console.log(a1()); // return 2

// OR:
function a2(){return 1;}
var b2 = a2;
a2 = function(){
  return b2() + 1;
};
console.log(a2()); // return 2