--- tags: javascript, note --- # const & let ES6 新增修改了些許功能,讓開發者可以避免掉一些老舊常見的問題,以及加入許多語法糖來增加開發速度! ## var 會遇到的問題 - **重複宣告會直接覆蓋掉**,而不會報錯。 ```javascript= var iLoveYou = false; ``` 若干行之後... ```javascript=5201314 var iLoveYou = true; ``` 你不會注意到幾萬行之前已經宣告過了,所以造就了一連串的大爆炸、俗成核爆。 (?) 別讓自己的電腦成為核爆家園(?)最好就是使用 let 及 const ,當你重複宣告的時候會直接報錯提醒。 - for loop & if/else 區塊內的變數其實都是屬於**全域變數** ```javascript= /* for loop */ for (var i = 0; i < 10; i++) { console.log(i); // output -> 1 2 3... 9 } console.log(i); // output -> 10 /* if/else */ if (true) { var a = 1; console.log(a); // output -> 1 } console.log(a); // output -> 1 ``` JS 的全域變數跟 CSS 的 !important 一樣,都是需要非常謹慎地使用,能不用就別用。 而如果你多次使用 for loop or if/else 判斷式,你也等於是不斷在全域重複宣告同一個變數的概念。 (相信大家都是按照潛規則命名為 i, j, k 之類的吧 XD) 接著我們來看看古早的解決辦法。 ```javascript= /* 古早味解決法: IIFE,這才是能夠限制 var 作用域緊箍兒 */ (function() { /* for loop */ for (var i = 0; i < 10; i++) { console.log(i); // output -> 1 2 3... 9 } /* if/else */ if (true) { var a = 1; console.log(a); // output -> 1 } })(); console.log(i); // output -> is not defined console.log(a); // output -> is not defined ``` ## 新變數英雄襲來! ```const``` 跟 ```let``` 只有一個地方不同,就是 ```const``` **無法重新賦值**、也因為如此,所以宣告時也就要立刻賦值,否則會報錯! ```const``` 原意為 "常數 (constant)",意即不可改變之數; 但是對於物件(包含陣列)的內容是可以修改的,單純不能 reassign。 解決的問題 - 避免變數被重複宣告 ```javascript let a = 1; let a = 'a'; // ouput -> SyntaxError: Identifier 'a' has already been declared ``` - 變數作用域更好限制 ```var``` 的作用域是在 function 內 ```let```、```const``` 的作用域是在 block 內,也就是 **{}** 內 for loop & if/else 變數也可以限制在範圍內了 ```javascript /* Block */ let a = 1; { let a = 'a'; console.log(a); // output -> 'a' } console.log(a); // output -> 1 ``` ```javascript /* for loop */ for (let i = 0; i < 10; i++) { console.log(i); // output -> 1, 2, 3... 9 } console.log(i); // output -> is not defined ``` ```javascript /* if/else */ if (true) { let a = 1; console.log(a); // output -> 1 } console.log(a); // output -> is not defined ``` ## 時戰應用技巧 ### 非同步經典考題: for 搭配 setTimeout ```javascript= for (var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 0); // 非同步的函式會先被放到 event stack } console.log(i); // output -> 10 /* 機著執行 setTimeout */ // output -> 10, 10, 10... 10 ``` 因為 ```var``` 的關係 i 成了全域變數, 所以當回頭過來執行事件柱列內容時 i 的值早已變成 10。 而使用 ```let``` 的話則可以解決這個問題, 因為變數包裹在 block 內一起送到事件柱列, 所以雖然非同步也是最後執行,但是變數會被個別保留, 以至於可以顯示出不同的數字,實作如下: ```javascript= for (let i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 0); // 非同步的函式會先被放到 event stack } console.log(i); // is not defined /* 機著執行 setTimeout */ // output -> 1, 2, 3... 9 ``` ### 讓 preventExtensions、seal 和 freeze 更加安全 雖然 preventExtensions、seal 和 freeze 可以限制物件,但如果物件是用 ```var``` 宣告出來的話,其實我可以強制重新 reassign 一個新的物件進去,一切就破解了; 因為物件是 pass by referance,所以我其實是修改變數的 referance,而非修改物件本身。 而如果物件都使用 ```const``` 去宣告,除了可以限制物件作為,更可以避免物件被不小心 reassign,所以更加地安全了! ## Hoisting 與 TDZ ```javascript console.log(a); // output -> Cannot access 'a' before initialization let a = 1; ``` 1. ```let``` 一樣會有創造階段。 2. 從創造到實際執行階段會出現 [TDZ](https://eddychang.me/es6-tdz/),在此區域/時間內無法呼叫、調用變數。 3. ```let``` 與 ```var``` 一樣有創造到執行的概念,但不會預先設定 undefined,而是出現錯誤提示。 4. 文件不會表明這與 ```var``` 的 Hoisting 相同。 :::info :bulb: 在執行流程一進入作用域建立變數,到變數開始可被存取之間的一段時間,就稱之為 TDZ (Temporal Dead Zone - 暫時性死區)。 :::
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up