[js 進階] JavaScript Scope

js framework 蓬勃發展(vue/angular/react),但若連 js 進階概念都不清楚,不就像還不會 abc 就想學如何用英文演講一樣嗎?
接下來會有一系列 js 核心的概念,讓你不管需要接觸哪個 framework 之前,都能更進一步認識 javascript
文章裡會提到


Scope

scope 簡單來說就是 where and how to look for things
js 有兩個 lexical scopes

  • 1. global
  • 2. function

只有在新增 function 時才會有新的 scope 出現,
而且只存在於此 function 內,其他像 if for 都無法建立新 scope

對於找尋一個變數的 lexical scoping rule,
會從此變數所存在的 function 開始找,
如果找到了就返回該變量,如果找不到就往上一層繼續找
以此類推直到 global 的環境

js-es5-scope-2
(圖片來自 datchley.name)

這個範例有三個 scope:
global scope 定義了 a 跟 foo;
foo() 定義了 b 跟 bar;
bar() 定義了 y 跟 c

以 bar() 來說,我在這個 scope 裡找變數 b ,
找不到時就往上一層 foo() 這個 scope 找,
找到了就會回傳 b = a*4

 
另外一個例子

因為變數 bar 只存在於 baz() 的 scope 裡

 

Shadowing

shadow 是在某變數的可視範圍內,定義同樣名稱的變數,
取用時是取用最近 scope 定義的變數

outerFun 定義的 x shadow了 global 的 x
console.log(x) // “Hi” 應証了定義在函數裡面的變數在外面是讀不到的
console.log(y) // “Red” 因為 y 沒有被宣告過,所以自動會變 window.y, 每一層都讀得到他因為是 global 的

 

undeclared vs undefined

在進入 hoisting 之前,想解釋一下 undeclared 跟 undefined 其實是很不一樣的東西

  • undefined: 是在可訪問 scope (目前 scope 跟 parents scope) 裡定義過但找不到值
  • undeclared: 是在可訪問 scope 沒有被定義過

 

Hoisting

這個例子第一眼你可能以為會輸出
undeclared
undeclared
undefined
1

但實際上卻會是
undefined
undefined
undefined
1

因為程式碼其實會自動把 var 過的變數跟 Function Declaration (涵式宣告式)
移到最前面 (Function Expression 並不會被移到最前面喔)
雖然表面上看不出來
但其實程式碼會默默變成

另一個例子

這邊我們知道程式碼會默默變成

所以答案就是
undefied
d is not a function

 

this

每一個 function 在被執行的時候都會有一個 reference 指向所屬的環境,就是 this
js 有四種函數調用方法

  • In normal function calls 一般呼叫涵式
  • Within methods on objects 方法調用
  • Within an object that has been constructed 建構涵式調用
  • A function invoked with .call, .apply, or bind 隱式調用

這解釋有點難懂,先來看看下面範例好了

答案是不知道,
因為 this 取決于執行這個 function 時的環境

例如 a(); // In normal function calls
那 this 就是 window

var obj = {};
obj.a = a;
obj.a() // Within methods on objects
這時 this 就是 變成obj

var b = new a()
這時 this 會是 a 這個 function 所產生的 object

a.call(obj) // A function invoked with .call, .apply, or bind
這時 this 就是也是obj

p.s JavaScript loses scope of this when used inside of a function that is contained inside of another function.