js函数提升和变量提升_关于在js中提升的真相

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.

当我查看幻灯片中varletconst之间的区别时,我发现自己对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

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

但是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. 🤔

在测试代​​码示例时,我意识到当我在声明变量的位置上方引用变量时,具有letconst的变量不会引发引用错误,即“未定义”。 相反,参考错误显示“初始化前无法访问'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.

如此看来,这些变量正在升起的地方! 否则,我们将收到错误消息,指出它们不存在,即“未定义”。 我们知道letconst仅在执行期间进行求值,因此不会像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变量被挂起,但未赋予任何值,它们会去哪里? 在未初始化的letconst变量等待评估的情况下,存在什么奇怪的炼狱术? 这些可怜的变量陷在了什么奇怪,肮脏JavaScript弱点中,无助地向他们的无情霸主(编译器和运行时)喊叫,让他们沉浸在初始化的阳光下?

This purgatory is called…

这个炼狱叫做……

.

.

.

The Temporal Dead Zone
zombie gif

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! Only let and const have an observable TDZ.

TDZ [Temporal Dead Zone]是一个存在变量但仍未初始化的时间窗口,因此无法以任何方式进行访问…从技术上讲, var也具有TDZ,但其长度为零,因此对于我们的程序而言是不可观察的! 只有letconst具有可观察的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.

一旦执行了代码并评估了变量声明, letconst变量将初始化并离开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?

“为什么临时死区甚至存在?” 你可能会问。 由于varletconst都已挂起,为什么我们不能像使用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 for let as well. In fact, if we make let 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.

因为varlet具有相似的属性,并且仅const具有时间性死区,所以对它们进行对齐不是更有意义吗? 是的,这是合乎逻辑的,但是众所周知,JavaScript并非总是如此。

let has a TDZ because const needs a TDZ, because let and const mimic var 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,因为letconst模仿var提升到(块)范围的顶部。 有呀。 圆吗? 再读几次。 ( 你不懂JS )

confused britney spears

那么,我们如何帮助这些无辜的变量避免这种毫无意义的绝望呢? (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函数提升和变量提升

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值