js中用let宣告變數出錯時,變數依然被宣告且無法再賦值是什麼原理?

時間 2021-05-31 17:50:59

1樓:貘吃饃香

瀉藥LexicalBinding : BindingIdentifier Initializer

Let bindingId be StringValue of BindingIdentifier.

Let lhs be ResolveBinding(bindingId).

Let rhs be the result of evaluating Initializer.

Let value be GetValue(rhs).

……lhs 已經被 binding

GetValue rhs 走到 IsUnresolvableReference(V) 時 throw aReferenceErrorexception.

這是第乙個語句情況。

由於 lhs 已經被 binding

再次 let 宣告走到 If envRec.

HasLexicalDeclaration(name) istrue, throw aSyntaxErrorexception.

(GlobalDeclarationInstantiation)

這是第二個語句情況

第三個語句異常規範無法解釋

對比其他引擎實現,應該是 V8 的 bug

(FF 的猴子沒這問題)

直接訪問 a 時候,V8 看樣子先去獲取了 varEnvRec ,由於沒有 var a,跑出 not defined。

試圖 let(var) a 時候則跑去先看了 lexEnvRec 有沒有 a,又被拋錯

(這時候 HasLexicalDeclaration 肯定有 a 了)

2樓:

這個問題出現的原因是let的暫存死區或臨時性死區(Temporal Dead Zone,TDZ,http://

jsrocks.org/2015/01/temporal-dead-zone-tdz-demystified/)。所謂暫存死區,就是指let宣告的變數必須先宣告並初始化成功後才能被引用,否則,這個變數就不能被引用,進入了暫存死區,就跟死了一樣。

第乙個錯,wtf未定義先引用,wtf處於暫存死區,所以報reference error,a同時未初始化成功,第二個錯,同乙個塊級作用域內,let不能宣告兩次,是語法錯誤,第三個報錯,因為a未初始化成功,所以a仍處於暫存死區,引用a報reference error。

這個問題的錯誤在於瀏覽器認為a沒有初始化成功,所以你永遠引用不到a。

3樓:魯喆

本人對原理理解不透,憑著結論反推,希望拋磚引玉。

首先,可以確定的是,不管是var還是let定義乙個變數,都包含宣告(declaration)和定義(definition)兩部分。

var a ( let b) 是宣告。而 a = wtf ( b = wtf) 是定義。

如果僅僅是var a,相當於 var a = undefined; 即先宣告乙個變數a,再定義為undefined。

let同理,let b; 相當於 let b = undefined; 只是,let只能在乙個塊(block)內,對乙個變數宣告一次。

因此可以解釋第二行的問題。 在第一行中 let a 已經對 a變數宣告過了,因此第二行再 let a就會報 already been declared 這個錯誤。

然後,根據我的測試結果:

用var宣告的同時定義給乙個未宣告的變數(var a = wtf),會報乙個wtf is not defined的錯誤,並給a賦值為undefined。

而let b = wft時,也會報乙個not defined的錯誤,但b這個變數就永遠都無法使用了,即不能重新宣告,也無法賦值。

推測結論是,let 與 var 不同,在第一次定義的時候,「似乎」直接把等號右邊的指標位址拿過來了,如果是乙個沒有指標位址的 not defined的變數(wtf),那麼剛宣告的這個變數(b)就再也引用不到了,導致無法修改。

程式語言用let等關鍵字宣告變數有什麼好處?

方應杭 如果沒有 let var,你如何得知 a 2 是在宣告 a 還是在對已有的 a 進行賦值呢?你不得不通過其他的特性來消除歧義。 望山 主要是用來明示這個地方你打算引入新變數,而不是使用前面 包括上層函式或全域性 已經出現過的變數,主要是給人看的,順便也能減少電腦進行語法分析的工作量。強型別語...

js中let與for迴圈輸入問題,為什麼輸出結果如下?

kkkKKKi 因為物件是引用基本型別,你可以把它理解成每次呼叫的時候都是使用的同乙個物件,因為這幾個物件共用乙個記憶體位址,所以最後無非就是同乙個物件用了兩次而已。陣列物件用的都是同乙個物件,當然資料就是一樣的了 善思即行 這裡不涉及作用域相關,主要是涉及到對引用型別變數改變問題。按題主的想法,出...

golang中,變數宣告之後就已經分配記憶體了嗎?比如互斥鎖,宣告之後就可以直接使用?

Tony Bai 在Go中變數宣告後就分配了記憶體,這是確定無疑的。但是否可直接用,還要看看下面兩個因素 如果變數是零值,那麼零值是否能直接用?變數值的意義是否符合業務邏輯要求。變數宣告有兩種形式 一種是宣告時未顯式賦值的,Go編譯器會為之賦予零值。比如 var a int a 0var s str...