iT邦幫忙

1

Day [2] — this:作用域 — JS之浸豬籠系列

如果你不知道這個系列為什麼叫這種激烈的名字可以看這篇:
Day [0] — JS之浸豬籠系列

如果你還沒看過這篇 ,可能會有點難理解今天這篇,建議你先企看看!
Day [1] — this:存在於物件 — JS之浸豬籠系列

Day [2] — this:作用域

直接進入範例主題!!!σ ゚∀ ゚) ゚∀゚)σ

//來個範例吧!

var a = 100;

var obj = {
  a: 200,
  fn: function() {
	    var test = function() {
      console.log(this.a)
    }
    test()
  }
}

obj.fn() //100

//....恩?為什麼是100?(゚д゚≡゚д゚)
//作用域去哪裡ㄌ?他本來還在的啊?

https://s3.us-west-2.amazonaws.com/secure.notion-static.com/fe7a6ddf-f115-431d-a6c4-d9b197aeb7ab/_2021-01-05_1.52.27.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210106%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210106T055509Z&X-Amz-Expires=86400&X-Amz-Signature=6a8bae753d3ddf979da3a63207be6c61ab07b46567242dc0932846ede9ee73d2&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22_2021-01-05_1.52.27.png%22

先不要激動,我們來看看到底發生了什麼事情....

//來個範例吧!
//範例一解析

var a = 100; 
//我們宣告 a = 100,這是一個全域變數

var obj = {
		a: 200, // a 在物件內的值為 200

				fn: function() {

				    var test = function() {
				    console.log(this.a)}** 

		    test() } //記住我們在這裡呼叫了test
}

obj.fn() //100

//解析一下
//讓我們用倒敘法回推,
//obj.fn() 所以我們要去找 obj(物件)裡的 fn 的值,
//往上看 fn,會發現 fn 是個函式,
//他會運算出 var test = function() {console.log(this.a)} 的值,
//記得我們在 fn 這個函式中 呼叫了 test();
//讓 this 去找出了第一行的 var a = 100; 

//什麼意思?
//意思是 this 自動去指向了 window !(沒想到吧)

//所以最後印出的值就是 obj.fn() //100


窩噗懂....為什麼會這樣?

讓我們印得比說得快!σ ゚∀ ゚) ゚∀゚)σ

//來個範例吧!
//範例二

function hello(){
  console.log(this)
}

hello()//猜猜這裡會印出啥?
//是......window !σ ゚∀ ゚) ゚∀゚)σ

https://s3.us-west-2.amazonaws.com/secure.notion-static.com/41dd3046-ea9c-4ca8-88bf-ef71598bd1a6/_2021-01-05_2.21.48.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210106%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210106T055705Z&X-Amz-Expires=86400&X-Amz-Signature=bc1781d27279d9b2b09b89b66ab088e7db68086db00ef06a547caa1f5af84157&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22_2021-01-05_2.21.48.png%22

從這邊開始我們就可以正式進入This的正題了!為啥在上面那個範例裡,this會指向window呢?

day[1]的文章 中提到『 this 在函數運行的時候自動指向 instance(物件實體) 的屬性。』

在上面那個範例中,我們並沒有讓 this 指向任何的物件,那 this 會指向哪呢?

你以為答案永遠是 window 嗎? 錯!σ ゚∀ ゚) ゚∀゚)σ


實際上在this沒有被指向 instance(物件實體)時,會指向的地方有這三種:

  1. 嚴格模式底下就都是undefined
  2. 非嚴格模式,瀏覽器底下是window
  3. 非嚴格模式,node.js 底下是global

一但脫離了物件,this 的值就沒什麼意義,在沒意義的情況底下就會有個預設值,而預設值也很好記,嚴格模式就是undefined,非嚴格模式底下就是全域物件。

(看懂這邊的話可以在往上看一次範例一)


看了上面的解析和範例,聰明的你應該已經發現 this 的值跟作用域跟程式碼的位置在哪裡完全無關,只跟「你如何呼叫」有關。

//來個範例吧!
//範例三

const obj = {
  value: 1,
  hello: function() {
    console.log(this.value)
  }
}

obj.hello() 
// 這裡會印出 1,我們怎麼呼叫的?

//我們最終的結果是要得到 obj.hello()
//obj我們已經知道他是物件,
//而其中 hello 是 function() {console.log(this.value)}

//在 obj這個物件中,this 會自動指向到 obj,
//當我們呼叫 obj.hello() 時等同於我們說 this 是 obj,
//為啥?因為他就是個代名詞!

const hey = obj.hello
hey() // 這裡會印出 undefined,我們怎麼呼叫的?

//為什麼換成 hey = obj.hello 就不是 1 了呢?
//答案也是:因為作用域。
//const hey = obj.hello 時,
//hey已經形成一個封閉的作用域(註一),
//所以 this 在 const(嚴格模式)底下就都是undefined。

//註一:
//const → 區塊作用域(block scope),其作用範圍是在它們被定義的區塊裡面。


引用及參考資訊

What's THIS in JavaScript ? [上]

淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂

this 的值到底是什么?一次说清楚


尚未有邦友留言

立即登入留言