iT邦幫忙

2021 iThome 鐵人賽

DAY 14
0
Modern Web

前端幼鳥三十天養成記系列 第 14

this指向who

我們很常會在function中看到使用this這個關鍵字。但它是甚麼,要怎麼用?聽說它的判斷方法很麻煩? 不急,我們先來看看生活中的this
https://github.com/Hsu-Linda/front-end-baby-bird/blob/main/this/%E6%88%91%E5%AE%B6%E4%BD%8F%E5%9C%A8%E5%8F%B0%E5%8C%97%E5%B8%82.gif?raw=true

生活中的this可以幫我們省去一直講重複的詞,讓句子比較簡潔。
程式裡的this,一樣幫我們省去一些詞,只不過這個詞,指向執行「程式碼」的「物件」。

生活中的「這個」「那個」常常搞到最後,有人都不知道在說哪個。
JS裡也不例外,一樣有「對牛談this」的情形。所以為了想正確設定執行程式碼的物件,我們需要來好好跟this討教討教


this 、 function 和 object

大部分情況下,this的值取決於呼叫function的方法。(此方法不是指,function或指隸屬於object底下的function:method,可以想成:語法的意思,不要誤會喔)
不同的呼叫方法,會讓this指向不同的呼叫function的物件。

ok,重點筆記。我們比剛剛又知道更多了一點:從指向「執行碼」的物件,變成指向「呼叫function」的物件。所以大概率this、function跟object是分不了家的~
→ this 指向 「呼叫函式(function)」的「物件(object)」


呼叫function的方法 與 this指向的「呼叫function的物件」

既然我們知道this會指向「呼叫function的物件」。那很明顯,當呼叫一個function時,我們要去綁定this和物件。我們的小任務就是要去觀察:在甚麼情況下,跟誰綁?(when,who)

四種繫結

  • 預設繫結
  • 隱含繫結
  • 明確繫結
  • new繫結

預設繫結 (Default Binding)

  • 甚麼時候使用when :
    • 方法名.()
    • 明確繫結,但沒定義this → i.e. 方法名.call(null,參數1,參數2,...,參數n) 、方法名.call()
      (後面再示範)
  • this跟誰綁who :
    • JS文檔最前面有 'use strict'; :
      在JS嚴格的監控下,沒人敢跟this綁,所以是undefined

    • 沒有寫'use strict' 非嚴格模式:this 跟全域物件綁
      還記得我們上一篇說全域物件是誰嗎?

      .

      .

      .

      沒錯,在瀏覽器是window物件,在node是global物件,所以這裡this是跟window物件綁

var str = 'Here is Global';
function logStr (){
	var str = 'Here is Local';
	console.log(this.str)
}

logStr();

猜猜是log出global還是local?反正我第一次是猜錯的

.

.

.

公布答案:Here is Global

解析:
跟我一樣錯的人往上看,when的第一個,方法名.(),這裡用的就是他。
既然如此,this就會跟全域物件window綁定。(可以直接在主控台打this看看,真的會看到window喔,沒有跟你唬,你說虎不虎)
接著this.str,意味著window.str,在全域找str這個變數,再之後就log出global來啦~ok下一關

先打個岔,剛剛稚鳥一下講函式,一下講方法的,他們一樣嗎?感受到困惑惹?~~釐清一下囉

function函式 method方法 係摀差?(是有差?)

  • function叫函式
  • 建一個object(物件),物件裡面設(屬性名)屬性
    (想叫啥都可以,如果是在主控台印字串,可以叫他logString屬性)
  • function(函式)令給(屬性名)屬性
    此時屬性值為function(函式)的屬性,稱為該objectmethod(方法)

程式碼長這樣

//object物件
var obj={};
//function函式 我們用宣告法
function  fk(){
	console.log('hi');
};
//等號左邊我們令一個屬性
//等號右邊我們把function函式,令給屬性 
//此時該屬性稱為物件object的方法method
//沒要執行,就不要小括號();想要執行,小括號就加好加滿
obj.fkProperty = fk;
  • 屬性存放的指是function的記憶體地址,所以function不會永遠屬於哪一個物件
    他可以把記憶體地址傳給別人,共享這個function

打岔結束

隱含繫結(Implicit Binding)

  • 甚麼時候使用when :當把他當作某物件的方法method調用(呼叫)時
  • this跟誰綁who :調用他的某物件
var str = 'Here is Global',
//obj1,obj2各自放不同的str
//obj1,obj2都把logStr function放入物件的log屬性中 (放進去才有辦法用隱含繫結調用壓)
		obj1={str:'Here is Obj1' ,log:logStr}, 
		obj2={str:'Here is Obj2' ,log:logStr , friend:obj1};
function logStr (){
	var str = 'Here is Local';
	console.log(this.str);
};

obj1.log();  //Here is Obj1
obj2.log();  //Here is Obj2
this.log();  //等價於 window.log()  全域沒有log這個function 
						 //Uncaught TypeError: this.log is not a function
obj2.friend.log();  //Here is Obj1

解析:

  • obj1.log();
    1. 在全域找到obj1物件,在obj1物件找到log method=(找到log屬性)
    2. 用()執行log method的值:logStr function 同時 this指向obj1
    3. 產生function內變數 var str = 'Here is Local';
    4. 執行 console.log(this.str) 等價於執行 console.log(obj1.str)
  • obj2.friend.log();
    1. 在全域找到obj2物件,在obj2物件找到friend屬性,friend屬性的值是obj1物件
    2. 因為區域內可以存取區域外的值(i.e. 全域的值),所以obj2可以存取在全域的obj1
    3. 在obj1物件找到log method
    4. 接續obj1.log()的解析

參考資料

JavaScript - This (1) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天


日常幹話:
今天就這樣愉快的結束了,明天還有三個方法呦


上一篇
FUNCTION
下一篇
this指向who(下)
系列文
前端幼鳥三十天養成記30

尚未有邦友留言

立即登入留言