[英]Why does this function expression behave differently than a function declaration?
Consider the following snippet: 请考虑以下代码段:
function myFunction(a){
console.log(a);
}
myFunction(1);
//1
var oldFunction = myFunction;
function myFunction(b){
console.log('intercept');
oldFunction(b);
}
myFunction(1);
//too many calls, console outputs intercept indefinitely
The code doesn't work properly and outputs "intercept" indefinitely. 代码无法正常工作并无限期地输出“拦截”。 Then I searched Stack Overflow and I found out that the following modified code worked as expected:
然后我搜索了Stack Overflow,我发现以下修改过的代码按预期工作:
function myFunction(a){
console.log(a);
}
myFunction(1);//1
var oldFunction = myFunction;
var myFunction = function(b){
console.log('intercept');
oldFunction(b);
}
myFunction(1);
//intercept
//1
My question is: why doesn't first code work as expected? 我的问题是:为什么第一个代码不按预期工作? I know there are differences between function declarations and function expressions (primarily due the hoisting behavior), but I'm still confused.
我知道函数声明和函数表达式之间存在差异(主要是由于提升行为),但我仍然感到困惑。
EDIT: Indeed is a hoisting behavior misunderstood. 编辑:确实是一个被误解的吊装行为。 I realize that the first code works if I execute it as the following:
我意识到第一个代码可以正常运行,如下所示:
eval(`function myFunction(a){
console.log(a);
}
myFunction(1);
//1
var oldFunction = myFunction;`);
eval(`function myFunction(b){
console.log('intercept');
oldFunction(b);
}
myFunction(1);`);
//1
//intercept
//1
This closes the question. 这就结束了这个问题。 When I execute the code separately becomes clear that the function myFunction was being hoisting.
当我单独执行代码时,很明显函数myFunction正在提升。
This is because of hoisting. 这是因为吊装。 In JavaScript, function declarations are hoisted meaning they are "hoisted" up to the top and declared first, and can be used before they are defined:
在JavaScript中, 函数声明被提升,意味着它们被“提升”到顶部并首先声明,并且可以在它们被定义之前使用:
foo(); //logs "in foo" function foo() { console.log("in foo"); }
On the other hand, function expressions are not hoisted like function declarations are. 另一方面,函数表达式不像函数声明那样被提升。
var
is still hoisted but it's value (the anonymous function) isn't given to the variable. var
仍然被提升但它的值(匿名函数)没有给变量。 For the purpose of making this more clear, your first snippet essentially looks like this (after function declarations and var
s are hoisted): 为了使这个更清楚,你的第一个片段基本上看起来像这样(在函数声明和
var
s被提升之后):
var oldFunction; function myFunction(a) { console.log(a); } function myFunction(b) { console.log('intercept'); oldFunction(b); } //myFunction(1); oldFunction = myFunction; myFunction(1);
(Side note: I've commented out the first call which throws an error because oldFunction
is undefined when you try to execute myFunction
the first time. The snippet above reproduces what you described in the first snippet of the question) (旁注:我已经注释掉第一个调用错误的调用,因为当你第一次尝试执行
myFunction
时, oldFunction
是未定义的。上面的代码片段会重现你在问题的第一个片段中描述的内容)
Thus, in your code, the first does not work because you have two functions of the same name. 因此,在您的代码中,第一个不起作用,因为您有两个相同名称的函数。 Thus the first
myFunction
is overridden and now it refers to the newer function. 因此,第一个
myFunction
被覆盖,现在它引用了更新的函数。 This will cause the code to recurse as the function is calling itself, making it run indefinitely. 这将导致代码在函数调用自身时递归,使其无限运行。
In your second example, it's essentially this: 在你的第二个例子中,它基本上是这样的:
var oldFunction; var myFunction; function myFunction(a) { console.log(a); } //myFunction(1); oldFunction = myFunction; myFunction = function(b) { console.log('intercept'); oldFunction(b); } myFunction(1);
In function hoisting, the whole declaration is hoisted, not just the name like with var
. 在功能提升中,整个声明被提升,而不仅仅是与
var
一样的名称。 So in the second example, the first function is not overridden when you call it the first time. 所以在第二个例子中,第一次调用它时不会覆盖第一个函数。 Then, when you do
oldFunction = myFunction
you assign oldFunction
a reference to myFunction
, which is the older function. 然后,当你做
oldFunction = myFunction
分配oldFunction
的引用myFunction
,这是老功能。 Executing it will execute the older function. 执行它将执行旧功能。 This will log:
这将记录:
intercept
1
As expected and will not recurse forever. 正如预期的那样,永远不会递归。
Only this part works: 只有这部分有效:
function myFunction(a){
console.log(a);
}
myFunction(1);
//1
as soon as you add the rest ... 只要你添加剩下的......
function myFunction(a){
console.log(a);
}
myFunction(1);
//1
var oldFunction = myFunction;
function myFunction(b){
console.log('intercept');
oldFunction(b);
}
myFunction(1);
//too many calls, console outputs intercept indefinitely
it will fail, because to the JS engine it reads like this: (in exactly this order) 它会失败,因为JS引擎的内容如下所示:(按此顺序)
var myFunction, oldFunction;
myFunction = function(a){
console.log(a);
}
//immediately overwriting myFunction by
myFunction = function (b){
console.log('intercept');
oldFunction(b);
}
myFunction(1); //this already fails, because `oldFunction` is undefined and therefore can't be called
oldFunction = myFunction;
myFunction(1); //too many calls, console outputs intercept indefinitely
Due to hoisting, in your code this function 由于吊装,在你的代码中这个功能
function myFunction(a){
console.log(a);
}
is completely eliminated and immediately replaced by 完全消除并立即取而代之
function myFunction(b){
console.log('intercept');
oldFunction(b);
}
before even a single expression is executed in the code. 甚至在代码中执行单个表达式之前。 stuff like
var oldFunction = myFunction
像
var oldFunction = myFunction
这样的东西
At first example oldFunction
is defined as 首先,示例
oldFunction
定义为
function myFunction(b){
console.log('intercept');
oldFunction(b); // calls `oldFunction` again
}
at second example oldFunction
is defined as 在第二个例子中,
oldFunction
定义为
function myFunction(a){
console.log(a);
}
In first code sniplet myFunction overridden by new myFunction as well oldFunction references the same so code executes in recursive order. 在第一个代码片段中,myFunction被新的myFunction覆盖,以及oldFunction引用相同的代码,因此代码以递归顺序执行。 But in second code second myFunction declared as annomous function which is not overriding old myFunction and when oldFunction get called it points to first myFunction only.
但是在第二个代码中,第二个代码myFunction声明为无法覆盖旧myFunction的函数,当oldFunction被调用时,它仅指向第一个myFunction。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.