你可以在声明后改变一个Javascript函数吗?

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

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

你可以使用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 

瞧。

编辑:更新以显示在一个更疯狂的情况下:

 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 

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

注意:如果你这样做的话,你真的应该重新考虑你的架构……当他/她正在查看一个应该返回1的函数定义时,你会在5年的时间里把一些糟糕的开发者弄糊涂了,但似乎总是返回2 ….

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

 // 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> ); 

而不是toSource(),你可以使用toString()来获取一个包含函数声明的string。 一些调用replace()来准备用于函数构造函数的string并修改函数的源代码。

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

从技术上讲,你正在失去一个函数定义,并用另一个函数定义。

如何呢,而不必重新定义的function:

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

我坚持jvenema的解决scheme,我不喜欢全局variables“老”。 旧的function保留在新的function中似乎更好:

 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 

所以你想要直接修改一个函数的代码,而不是仅仅为一个已经存在的variables重新分配一个不同的函数。

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

MDN上的文档列出了函数对象的属性和方法。 他们都没有给我们机会从外面操纵职能机构。

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

所有可行的解决scheme都坚持“function包装法”。 其中最可靠的似乎是rplantiko之一 。

这样的function包装很容易被抽象掉。 概念/模式本身可以被称为“方法修改”。 它的实现绝对属于Function.prototype 。 标准的原型方法修饰符如beforeafteraroundafterThrowing以及afterFinally

至于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 

…使用[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()); 

如果您正在debuggingJavaScript,并希望查看代码的更改如何影响页面,则可以使用此Firefox扩展来查看/更改javascripts:

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

你能不能以后再定义它? 当你想改变尝试只是重新定义它:

 a = function() { return 2; } 

绝对。 只需分配给它一个新的function。

这是一个基于控制时间eworld.ui eworld.ui http://www.eworldui.net的;eworld.ui示例

有一个TimePicker eworld.ui ,其中JavaScript是从外面无法访问,您不能find任何与这些控件相关的js。 那么如何添加一个onchange事件到timepicker?

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

首先你必须复制这个函数里面的代码。

评估… 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 + "();"); 

}

现在

使用之前保存的代码重新分配相同的源代码,但添加任何你想要的。

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 +“();”);

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

我已经添加了我的function,所以现在我可以模拟一个onchange事件,当我select一个时间。

RaiseChange(…)可以是任何你想要的。

  function get_func(func) {//from StackOverflow //var args = Array.prototype.slice.call(arguments); var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; var ARGUMENT_NAMES = /([^\s,]+)/g; var fnStr = func.toString().replace(STRIP_COMMENTS, ''); var args = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); //var code = func.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]; var code =fnStr.slice(fnStr.indexOf("{") + 1, fnStr.lastIndexOf("}")); var func_full_name=fnStr.substr(0, fnStr.indexOf('{') ); var func_name=fnStr.slice(9, fnStr.indexOf('(')); if(args === null){ args = []; } return { func_name:func_name,func_full_name:func_full_name, code:code, args:args}; } function str_trim(str){ //replaces multi-line characters return str.replace(/\n/g,'').replace(/^ +| +$/gm, '').trim(); } function edit_func(func,callback){ var a_func=get_func(func); var lines = a_func.code.split('\n'); var output=[]; for(var i=0;i<lines.length;i++){ var code=str_trim(lines[i]); if(code!=''){ code =callback(code,output.length,a_func.args); output.push(code); } } //var test=Function(['a','b'],'alert(a);alert(b);'); //test(1,2); //func=Function(a_func.args,output.join('\n')); //return func; var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.text =a_func.func_full_name+'{'+ output.join('\n') + '}' ; head.appendChild(script); } function test(id) { var x, y; x = 5; y = 10; alert(x + y); alert(id); } edit_func(test,function(code,line,args){ if(line==3){ return 'alert(x*y);'; } return code; }); test(3); 

试试这一个它会改变原来的function,使用一个新的代码检查每一行代码的callback。