js函数提升和变量提升
Earlier this week I was preparing to give a tech talk about some foundational JavaScript concepts to know for tech interviews. As always, when prepping content to share, I was obsessively going over the details to make sure all of my facts were correct. I would never want to steer anyone wrong. After all, these articles and talks are made to help people, not hinder them!
本周初,我正准备就一些基本JavaScript概念进行技术演讲, 以供技术采访了解 。 与往常一样,在准备共享内容时,我总是沉迷于细节以确保所有事实都是正确的。 我永远也不想引导任何人犯错。 毕竟,这些文章和谈话是为了帮助人们而不是阻碍他们!
var,let和const (var, let, and const)
As I was reviewing the slides for the difference between var
, let
and const
, I found myself questioning the statement that var
is the only one hoisted. This ‘fact’ was told to me by an interviewer awhile back, and I figured he must be right due to his extremely reputable title and company.
当我查看幻灯片中var
, let
和const
之间的区别时,我发现自己对var
是唯一被悬挂的声明的说法提出了质疑。 一位面试官不久前告诉我这个“事实”,由于他的头衔和公司声誉极佳,我认为他一定是对的。
I knew that yes, var
is definitely hoisted and initialized with an undefined
value. I also learned that if you have an undeclared variable inside of a function, it will automatically be hoisted to the top of the scope during the compilation phase, and initialized as a global variable with an imaginary var
like so:
我知道,是的, var
肯定是用undefined
值吊起和初始化的。 我还了解到,如果函数内部有未声明的变量,则它将在编译阶段自动提升到作用域的顶部,并使用虚构的var
初始化为全局变量,如下所示:
![code example with var hoisting](https://i-blog.csdnimg.cn/blog_migrate/edd0bbd37300981104805faebc744c63.png)
In this example, when exterminator()
is called, the now global variable of cockroachA
(which was initialized with undefined
) is initialized with its new value “I’m alive!”. cockroachA
has escaped the exterminator. He lives!!
在此示例中,当调用exterminator()
时, cockroachA
现在的全局变量(已使用undefined
初始化)将使用其新值“ I'm alive!”进行初始化。 cockroachA
逃脱了除虫剂。 他住!!
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/38440b35e38ce6c70d7daa440c8e36ed.png)
但是let和const呢? (But what about let and const?)
As I was testing out code examples, I realized that when I referenced a variable above where they were declared, the variables with let
and const
weren’t throwing a reference error saying “not defined”. Instead the reference error said “Cannot access ‘a’ before initialization”. Hmm. 🤔
在测试代码示例时,我意识到当我在声明变量的位置上方引用变量时,具有let
和const
的变量不会引发引用错误,即“未定义”。 相反,参考错误显示“初始化前无法访问'a'”。 嗯 🤔
console.log(a)
// ReferenceError: Cannot access 'a' before initialization
console.log(b)
// ReferenceError: Cannot access 'b' before initializationlet a = 'Remy'
const b = 'Linguine'console.log(a) // 'Remy'
console.log(b) // 'Linguine'
So it seems these variables are being hoisted somewhere! Otherwise we would’ve received an error that they didn’t exist, i.e. “not defined”. We know that let
and const
are only evaluated during the time of execution, so they aren’t initialized with an undefined
value like variables with var
do.
如此看来,这些变量正在升起的地方! 否则,我们将收到错误消息,指出它们不存在,即“未定义”。 我们知道let
和const
仅在执行期间进行求值,因此不会像var
do那样使用undefined
值进行初始化。
So if the let and const variables are being hoisted, but not given any value, where do they go? What weird sort of purgatory exists where uninitialized let
and const
variables wait to be evaluated? What bizarre, seedy JavaScript underbelly are these poor variables trapped in, shouting out helplessly to their merciless overlords (the Compiler and the Runtime) to let them bask in the sunlight of initialization??
因此,如果let和const变量被挂起,但未赋予任何值,它们会去哪里? 在未初始化的let
和const
变量等待评估的情况下,存在什么奇怪的炼狱术? 这些可怜的变量陷在了什么奇怪,肮脏JavaScript弱点中,无助地向他们的无情霸主(编译器和运行时)喊叫,让他们沉浸在初始化的阳光下?
This purgatory is called…
这个炼狱叫做……
.
。
.
。
.
。
![The Temporal Dead Zone](https://i-blog.csdnimg.cn/blog_migrate/97175cdc1f898d0226772e0a2b1aaa97.png)
![zombie gif](https://i-blog.csdnimg.cn/blog_migrate/c7feef534fe32dddaf0732c30d563a0e.png)
But seriously, this is real!
但是说真的,这是真实的!
According to the book You Don’t Know JS:
根据《 您不懂JS 》一书:
The TDZ [Temporal Dead Zone] is the time window where a variable exists but is still uninitialized, and therefore cannot be accessed in any way… A
var
also technically has a TDZ, but it's zero in length and thus unobservable to our programs! Onlylet
andconst
have an observable TDZ.TDZ [Temporal Dead Zone]是一个存在变量但仍未初始化的时间窗口,因此无法以任何方式进行访问…从技术上讲,
var
也具有TDZ,但其长度为零,因此对于我们的程序而言是不可观察的! 只有let
和const
具有可观察的TDZ。
Once the code is executed and the variable declarations are evaluated, the let
and const
variables will initialize and leave the Temporal Dead Zone, making them available to use for the rest of the scope.
一旦执行了代码并评估了变量声明, let
和const
变量将初始化并离开Temporal Dead Zone,使它们可用于其余范围。
“Why does the Temporal Dead Zone even exist??” you may ask. Since var
, let
and const
are all hoisted, why couldn’t we just auto-initialize them all with an undefined
value, the way we do with var?
“为什么临时死区甚至存在?” 你可能会问。 由于var
, let
和const
都已挂起,为什么我们不能像使用var那样用undefined
值自动初始化它们呢?
The reason: It’s all const
's fault.
原因: 都是 const
的错。
Because const
cannot be redeclared with a new value, if it was initialized as undefined
during compilation, and later initialized with a new value during execution, this would go against everything const
stands for! You might think, “Ok I guess that makes sense, but why do we also do this for let
then?”
因为不能用新值重新声明const
,所以如果在编译过程中将其初始化为undefined
,然后在执行期间将其初始化为新值,则这将与const
代表的一切const
! 你可能会想,“好吧,我想这是有道理的,但为什么我们还这样做了let
呢?”
Well, TC39 made the decision: since we need a TDZ for
const
, we might as well have a TDZ forlet
as well. In fact, if we makelet
have a TDZ, then we discourage all that ugly variable hoisting people do. So there was a consistency perspective and, perhaps, a bit of social engineering to shift developers' behavior. (You Don’t Know JS)好吧,TC39做出了决定:由于我们需要
const
的TDZ,因此我们也可能需要let
TDZ。 实际上,如果让let
拥有TDZ,那么我们就不鼓励所有可变的吊装人员这样做。 因此,有一个一致性的观点,也许还有一些社会工程学可以改变开发人员的行为。 ( 你不懂JS )
Wouldn’t it make more sense for var
and let
to be aligned since they have similar properties, and for only const
to have a Temporal Dead Zone? Yes, that would be logical, but as we know, JavaScript is not always so.
因为var
和let
具有相似的属性,并且仅const
具有时间性死区,所以对它们进行对齐不是更有意义吗? 是的,这是合乎逻辑的,但是众所周知,JavaScript并非总是如此。
let
has a TDZ becauseconst
needs a TDZ, becauselet
andconst
mimicvar
in their hoisting to the top of the (block) scope. There ya go. Too circular? Read it again a few times. (You Don’t Know JS)
let
具有TDZ,因为const
需要一个TDZ,因为let
和const
模仿var
提升到(块)范围的顶部。 有呀。 圆吗? 再读几次。 ( 你不懂JS )
![confused britney spears](https://i-blog.csdnimg.cn/blog_migrate/1b99936b28b02729eef21a66bc040dcf.png)
那么,我们如何帮助这些无辜的变量避免这种毫无意义的绝望呢? (So how do we help these innocent variables avoid this senseless pit of despair?)
The best way to get around the TDZ and avoid potential reference errors is to declare your variables at the top of the scope. In addition to avoiding errors, it makes your code more readable by grouping together all of the available variables in one place.
避开TDZ并避免潜在参考误差的最佳方法是 在作用域的顶部声明变量。 除了避免错误之外,通过将所有可用变量集中在一个位置,它还使您的代码更具可读性。
There you have it my friends, just one more JS oddity to add to your ever-growing list!
在那里,我的朋友们到这里了,只需再增加一个JS怪异功能即可添加到您不断增长的列表中!
What’s the strangest JS quirk you’ve come across? Let me know in the comments below!
您遇到的最奇怪的JS怪癖是什么? 在下面的评论中让我知道!
翻译自: https://levelup.gitconnected.com/the-truth-about-hoisting-in-js-8ac79a08a5f9
js函数提升和变量提升