简体   繁体   English

为什么这个函数表达式的行为与函数声明不同?

[英]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.

相关问题 为什么以函数声明为参数的setInterval()与匿名函数的工作原理不同? - Why setInterval() with a declaration of a function as an argument works differently than with anonymous function? 为什么重新定义自己的功能在Chrome / IE和Firefox中表现不同? - Why does a function redefining itself behave differently in Chrome/IE and Firefox? 为什么removeChild函数的行为与列表项和i标记不同? - Why does removeChild function behave differently with list items and i tag? 为什么此全局Javascript变量在函数内部和外部的行为有所不同? - Why does this global Javascript variable behave differently inside and outside of a function? 为什么jQuery的行为与javascript不同? - Why does jQuery behave differently than javascript? 为什么 oninput 事件在 Angular 中的行为与在 JavaScript 中的行为不同? - Why does the oninput event behave differently in Angular than it does in JavaScript? .then(Promise.mapSeries(...))的行为与.then(function(){return Promise.mapSeries(...);})的行为不同吗? - Does .then(Promise.mapSeries(…)) behave differently than .then(function() { return Promise.mapSeries(…); })? 我们的 await 关键字在 for await of 循环中的行为与普通异步 function 中的行为有何不同? - How differently does our await keyword behave inside the for await of loop than in a normal async function? 函数声明比函数表达式快? - function declaration faster than function expression? 为什么是 JavaScript 函数声明(和表达式)? - Why JavaScript function declaration (and expression)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM