ItIron2021
Javascript
昨天我們透過了一個相當經典的題目探討了基本的作用域(scope)與變數賦值的概念,讓我們沿續這兩個概念繼續進行另一個題目的練習吧! 由於只是概念的應用複習,今天的篇幅甚至會再更短一些! 一起放輕鬆來學習吧!
請問下方的程式碼會有什麼輸出結果?
(function(){
var a = b = 3
})();
console.log("a defined? " + (typeof a !== 'undefined'));
console.log("b defined? " + (typeof b !== 'undefined'));
這個題目也算相對常見的基本題型之一,當時是在一間博奕公司給的現場測驗中遇到這題目,好在之前自己練習時就有遇到類似的情境才不至於翻車?
先防雷,來張思考圖片擋一下,思考結束後再往下滑吧!
最終的輸出結果如下
a defined? false
b defined? true
最終a是個未定義的變數,但b則是一個已經定義的變數,且其值為3,那為什麼會有這樣的結果呢? 我們一個個重點來看吧!
很多人會以為下面兩種寫法是完全等價的
var a = b = 3
-----我是分隔線-----
var a = 3
var b = 3
但事實上由於運算子相依性(associativity,也有人說運算子結合率),上方的程式碼賦值部份會是右 -> 左進行,也就是說實際上會是這樣的
b = 3
var a = b
但這樣又有什麼差別呢? 關鍵在於b變成一個類似全域變數的存在,會掛在當下指向的global object下,以瀏覽器為例便是在window物件下
而var宣告的變數我們在昨天提過,它是functional scoped,也就是說a這個變數僅存在於該立即執行函數(IIFE)中,離開那個函數便無法被使用,最終自然變成not defined的變數囉!
也因此你在很多很多的教材中都會看到永遠都要用var、const/let來宣告變數,以免造成這樣意料之外的行為,現在許多的框架都會自動套用strict mode,在嚴格模式下就會預先替你把這樣的錯誤抓出來囉!
順帶一提,一次賦值多個變數的寫法是這樣的,利用這樣的寫法修改題目後就會看到我們預期的結果囉!
scope、變數宣告與賦值、運算子相依性
本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!
Danny大,看完文章幫助我這個小菜雞對於Scope及賦值的概念又有更深一層的思考,不過有遇到一個疑問:
在上述的例子中,var a = 3, b = 3,a、b這兩個變數為什麼會是undefined,而非皆為defined呢?(自己的理解是兩個變數都被賦值過了)
你的理解沒有錯! 最後的例子其實不管是a、b都是宣告且賦值過的,不過就像我們在day1提到的,var宣告的變數屬於functional scoped,也就是說a, b兩變數很遺憾地只存在於那個立即執行函數中,你在其他地方試著印出來自然會是not defined囉!
另外請教關於block scoped,是只要用括號,不管是哪一種括號,即:用{}或(),都有區隔作用域的效果嗎?
而[]是不是都只用來表示陣列呢?
另外請教關於block scoped,是只要用括號,不管是哪一種括號,即:用{}或(),都有區隔作用域的效果嗎?
不用想得這麼複雜,簡單說就是絕大多數大括號{}包起來的程式碼區域就會切成一個block,像是條件式、迴圈甚至是函數都是常見的block。
[]是不是都只用來表示陣列呢?
這問題就有點突然了,不過我想你會這樣問應該是因為物件的宣告看起來也像是一個block. 但你可以放心,在js中[]確實就是表示陣列這個資料結構,沒有其他意思了。
Danny大的解惑很清楚明瞭,謝謝!
不會~! 很高興有幫上忙,若之後有其他問題或發現文章有什麼錯誤都歡迎你提出!