2017年的事情仍是2017年完成吧。话很少说,如今开始:javascript
以前翻译过两篇发表在Medium上的两篇文章,关于变量和函数提高的问题。后来发现,一个读者(Gavin Orland)与做者(Bhuvan Malik)就函数和变量提高的问题产生了分歧,是留言形式的。最后做者还专门又写了一篇文章来回应问题,我想也是想让你们都看见吧。因此我本身整理一下,现将他们的讨论也作一个搬运吧。java
Gavin Orland:
Explanations 1 and 3 are slightly incorrect as function declarations are actually hoisted above variable declarations.
解释1和3有点不正确,实际上函数声明其实是在变量声明之上提高的。git
Bhuvan Malik:
For the first question’s behind the scenes, I have purposely shown the effects of hoisting only inside the functional scope of b().
对于第一个问题,我刻意仅在b()的功能范围内展现了提高的效果。github
As for the third question, var hoisted = “I’m a variable”; comes first and therefore the variable “hoisted” should be hoisted first with an “undefined” value. I could be wrong in which case you can point me to a source which proves me wrong, in which case I’d be happy make the change. ?
第三个问题:var hoisted = “I‘m a variable’”; 所以首先应该提高“提高”的变量,而且具备“undefined”的值。我多是错的,在这种状况下,你能够指出个人来源,证实我错了,在这种状况下,我会很高兴作出改变。?app
Gavin Orland:
Here’s what goes on behind the scenes for explanation 3:ide
function parent() { // Function declaration hoisted first function hoisted() { return "I'm a function"; } // Variable re-assigned (declaration ignored) hoisted = "I'm a variable"; return hoisted(); } console.log(parent());
Here’s a source for this.
源码在这里。函数
Bhuvan Malik:
What you’re trying to say is correct. However, saying that function declarations get hoisted “above” variable declarations, which implies that variable declarations “get hoisted below” is wrong. In such a case, what is happening is that the hoisting of var declarations simply gets ignored. I will update this. ?
你想证实你说的是对的。然而说函数声明提高在变量声明提高之上,在暗示变量声明“提高在下面”是错的。在这样的状况下,发生的事情就是简单地忽略var声明的提高。 我会更新这个。?学习
Gavin Orland:
I’m not “trying” to say anything, I’m simply saying it: function declarations are hoisted above variable declarations. What is unclear about that? Yes, therefore variable declarations are then logically hoisted below function declarations, if you want to think about it like that. It is not wrong to say that — please prove to me that is wrong.
我没有试着说什么,我只是在说:函数声明被提高到了变量声明之上。有什么不清楚的呢?是的,所以变量声明在函数声明下面逻辑地提高,若是你以为他是这样,那样说也没错--请向我证实我是错的。this
In your first reply you said:
在你第一次回复中你说:翻译
var hoisted = “I’m a variable”; comes first and therefore the variable “hoisted” should be hoisted first with an “undefined” value
This is incorrect — a declaration will be hoisted after the function with this value. Then the string value is immediately assigned to it.
这是错的-- 一个声明将在具备这个值的函数以后被提高。而后,字符串值当即分配给它。
Indeed, in the case of example 3, the declaration is ignored (in contradiction to your explanation), as I explained, because the variable has already been declared in the form of the function, but in other cases (such as example 1, which you do not want to correct) function declarations are hoisted first, then variable declarations.
确实,在案例3的状况中,这个声明被忽略(与你的解释相矛盾),正如我所解释的,由于变量已经以函数的形式被声明了,但在其余状况(如示例1,您不想纠正)函数声明首先被提高,而后是变量声明。
Function and variable declarations are always hoisted in this manner, the assignment to the variable will take place wherever it appears in the code.
函数和变量声明老是用这样的方式被提高,变量的赋值将在代码中的任何位置出现。
It’s odd you should accept my correction and then somehow claim you are right and I am wrong?! Anyway, I see you have now corrected the article (otherwise very good, and thanks for writing it).
这很奇怪,你应该接受个人更正,而后以某种方式声称你是对的,我错了?不管如何,我看你如今已经纠正了这篇文章(其余的很是好,谢谢你写了这些)。
Bhuvan Malik:
First of all, thanks for correcting me sir and I appreciate your explanations. You say that variable declaration will get hoisted after the function with an “undefined” value, and then the string value will be immediately assigned. My doubt here is that what if we only have the variable declaration without a string value being assigned like so:
首先,感谢先生纠正我,我感谢你的解释。你说那个变量声明在函数以后被赋值“undefined”,而后字符串值将当即分配。这里个人疑问是,若是咱们只有变量声明没有被赋值的字符串值,以下所示:
function parent() { var hoisted; function hoisted() { return "I'm a function"; } return hoisted(); } console.log(parent());
If variable declaration does get hoisted after the function, then behind the scenes for this according to your explanation should be:
若是变量声明在函数以后被挂起,那么根据你的解释,这个后台应该是:
function parent() { // Hoisted first function hoisted() { return "I'm a function"; } // Hoisted second with a value of undefined var hoisted; return hoisted(); } console.log(parent());
If the variable declaration is indeed hoisted second, then hoisted should finally get the value of “undefined” after the hoisting of the function and the program should finally throw an error because hoisted is no longer a function.
若是变量声明确实是第二次提高的话,那么在提高函数后最终获得的值是“undefined”,程序最终会由于提高函数而抛出一个错误。
However, the output still comes out to be “I’m a function”.
然而,这里输出的是“I’m a function”
This is the reason why I think there is no variable declaration hoisting happening here. I agree that a variable declaration hoisting in such a case simply gets ignored. Getting me?
Again, I could be wrong. I’m just trying to learn here by discussing with you.
就是这个缘由我认为变量声明没有提高。 我赞成,在这种状况下提交的变量声明只是被忽略。 再联系我?再次,我多是错的。 我只是想经过讨论和你一块儿来学习。
Gavin Orland:
No problem, I can explain this. In fact I think we have already covered it, really.
没问题,我能解释这个。事实上我认为咱们已经把它覆盖了,真的。
Variable declarations are hoisted after (or below) function declarations. But, in the case where the names match function declarations (or any variable already declared), they have no effect, so are ignored.
变量声明在函数声明以后(或者下面)被提高。可是,在名称匹配函数声明的状况下(或任何已经声明的变量),它们没有效果,所以被忽略了。
So, redeclaring a variable does not render it undefined, it has no effect. Only re-assigning an already declared variable has an effect.
所以,从新声明变量不能给与它“undefined”,这没有效果。只能从新给一个已经声明的变量分配才会有效果。
Here’s a simple but illuminating example of this variable hoisting, btw:
这是个关于变量提高的简单又又明确例子:
console.log(x); // undefined var x = y; function y(){} console.log(x); // function y(){}
This is understood as:
这被理解为:
function y(){} var x; console.log(x); // undefined x = y; console.log(x); // function y(){}
Bhuvan Malik:
Got it now. Thank you so much!
如今明白了。 很是感谢!
以上就是这位读者(Gavin Orland )和做者(Bhuvan Malik)之间的讨论。仍是获得些启发。由于读者给的源码但是大名鼎鼎的《你不知道的JavaScript》里面的例子。我也算完成了搬运,好了~ 能够没有欠债(我本身的债)的度过2017了。
Peace ✌️