JavaScript 函数重定义
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3227222/
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
JavaScript function redefinition
提问by David K.
Is it possible to redefine a JavaScript function from within its own body. For example, could I do the following?
是否可以从 JavaScript 函数内部重新定义它。例如,我可以执行以下操作吗?
function never_called_again(args) {
// Do some stuff
never_called_again = function (new_args) {
// Do some new stuff
}
}
Is the above valid and does it have the correct semantics? I don't want to create a new global variable with the old function name, because I'm trying to do this kind of thing not in the global scope, but from various object scopes, and I don't want name clashes when I redefine the function within those local scopes.
以上是否有效,是否具有正确的语义?我不想用旧的函数名创建一个新的全局变量,因为我试图在全局范围内而不是在各种对象范围内做这种事情,而且我不希望名称冲突在这些局部范围内重新定义函数。
采纳答案by Brock Adams
Yes, you can redefine a function that way.
是的,您可以通过这种方式重新定义函数。
Running This:
运行这个:
function never_called_again(args) {
console.log('Func 1', args);
never_called_again = function (new_args, x) {
console.log('Func 2', new_args, x);
}
}
never_called_again('arg A', 'arg B');
never_called_again('arg A', 'arg B');
Yields this:
产生这个:
Func 1 arg A
Func 2 arg A arg B
回答by gblazex
It is indeed possibleto redefine a function from its body. The technique is used in the so-called Lazy Function Definition Pattern.
确实可以从函数体重新定义函数。该技术用于所谓的Lazy Function Definition Pattern。
It looks like this:
它看起来像这样:
// Lazy Function Definition Pattern
var foo = function() {
var t = new Date();
foo = function() {
return t;
};
return foo();
}
This function stores the Date of the first call, and returns this Date afterwards.
此函数存储第一次调用的日期,然后返回此日期。
If you comparethis with the module pattern, the difference is that the initialization only happens when it's first called, not when it's defined. For costly initializationsit can be a huge benefit.
如果将其与模块模式进行比较,区别在于初始化仅在首次调用时发生,而不是在定义时发生。对于代价高昂的初始化,这可能是一个巨大的好处。
// Conditional Module Pattern
var foo = (function() {
var t;
return function() {
if (t) {
return t;
}
t = new Date();
return t;
}
})();
回答by Gregory Patmore
It's totally possible to redefine a function object into whatever you want upon the first call.
完全有可能在第一次调用时将函数对象重新定义为您想要的任何内容。
The reason this is possible is because the assignment evaluations is handled from right to left. This means that the scope of the function is captured when you execute it (in this case, when you call the function).
这是可能的原因是因为分配评估是从右到左处理的。这意味着函数的作用域在您执行时被捕获(在本例中,当您调用该函数时)。
This really means that at the time of execution, the function object that is getting executed and the original function definition are actually two different things, which allows redefinition of the original function as, well... anything really.
这真的意味着在执行时,正在执行的函数对象和原始函数定义实际上是两个不同的东西,这允许重新定义原始函数,嗯......任何真的。
One of the best (and coolest) ways to use this is by creating a function that is, in essence, its own factory. In this way you don't have to carry around a lot of object definitions that aren't going to be used.
使用它的最好(也是最酷的)方法之一是创建一个函数,它本质上是它自己的工厂。通过这种方式,您不必携带很多不会使用的对象定义。
Example:
例子:
d = function(type){
switch(type.toUpperCase()){
case 'A' :
d = (
function(){
return {
name : 'A',
getName : function(){return this.name;}
};
}
)();
break;
case 'B' :
d = (
function(){
return {
name : 'B',
getName : function(){return this.name;}
};
}
)();
break;
default:
d = (
function(){
return {
name : 'DEFAULT',
getName : function(){return this.name;}
};
}
)();
break;
}
};
console.dir(d);
d('A');
console.dir(d);
console.log(d.getName());
回答by Douglas
Your example is basically the same as:
您的示例与以下内容基本相同:
var never_called_again = function(args) {
//do some stuff
never_called_again = function (new_args) {
//do some new stuff
}
}
Since you probably know that this works:
因为您可能知道这是有效的:
var a = 1;
function myFunction() {
//do some stuff
a = 2;
}
myFunction();
alert(a) //==> 2
it's clear that the first example works too.
很明显,第一个例子也有效。
Whether you actually wantto do this or not is a more open question. Will it make the code harder to understand?
你是否真的想这样做是一个更悬而未决的问题。它会使代码更难理解吗?
回答by naikus
Yes, it's possible, and it will not create a global function. I verified this in Internet Explorer 6, Firefox, Chrome, and Opera. Consider the following code:
是的,这是可能的,并且不会创建全局函数。我在 Internet Explorer 6、Firefox、Chrome 和Opera 中验证了这一点。考虑以下代码:
<head>
<title>Never called again</title>
<style type="text/css">
</style>
<script type="text/javascript">
function hello() {
function never_called_again(args) {
alert("Hello world " + never_called_again);
//do some stuff
never_called_again = function (new_args) {
//do some new stuff
alert("hello " + never_called_again);
}
}
never_called_again();
never_called_again();
}
</script>
</head>
<body onload="">
<button onclick="hello(); never_called_again();">Call</button>
</body>
This will print "Hello World {function code}" the first time of the never_called_again and the second time it will print "hello {changed function code}" the second time.
这将在 never_called_again 第一次打印“Hello World {function code}”,第二次第二次打印“hello {changed function code}”。
But when it's being called on button's onclick, it will throw an error saying that the function is not defined, clearly indicating that the function was re-defined (and not created globally).
但是当它在按钮的 onclick 上被调用时,它会抛出一个错误,说该函数未定义,清楚地表明该函数是重新定义的(而不是全局创建的)。
回答by Nat
Strictly speaking, no, it isn't possible to redefine a JavaScript function at all. Though it's kind of a matter of semantics.
严格来说,不,根本不可能重新定义 JavaScript 函数。虽然这是一个语义问题。
A function may overwrite its reference within a certain scope with anotherfunction, which serves as a sleight of hand where another function appears in the place of the first. e.g.
一个函数可能会在某个范围内用另一个函数覆盖它的引用,这是一个技巧,另一个函数出现在第一个函数的位置。例如
greet_once = function() {
console.log('Hello.');
greet_once = function() { console.log('Can I help you?') };
};
Similarly a function may use the state of a closured scope to behave differently the second time its called (obviously not "redefinition").
类似地,一个函数可能会使用封闭作用域的状态在第二次调用时表现出不同的行为(显然不是“重新定义”)。
The following example illustrates why the above pattern isn't redefinition because it depends on the parent scope which may not be shared with the calling scope.
下面的示例说明了为什么上述模式不是重新定义的,因为它取决于可能不与调用范围共享的父范围。
greet_always = function() {
greet_once = function() {
console.log('Hello.')
greet_once = function() { console.log('Can I help you?') }
};
return greet_once()
}()
greet_always()
greet_always()
The function being called as greet_always(which always prints 'Hello.') is the same one, assigned originally to greet_once.
被调用的函数greet_always(总是打印 'Hello.')是同一个,最初分配给greet_once.
The closest I believe you can get to redefining a function is to reassign its apply and call methods, which produces a scenario where myFunction.call()is different from myFunction(), which is weird but conceivably useful.
我相信你能重新定义一个函数的最接近的方法是重新分配它的 apply 和 call 方法,这会产生一个myFunction.call()不同于的场景myFunction(),这很奇怪但可以想象很有用。

