iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0

🔔 this 是誰?
誰呼叫 thisthis就是誰!
不過...this 很有骨氣,誰拿箭瞄準他(=>),或是對他數 123(setTimeout),甚至要求他立刻去做((function () {...})();),this 誰都不理直接找窗戶透氣!

this 的作用域


MDN 文件:this

Hi, I'm Kuku. 這裡的我是指 Kuku。
Hi, I'm Ting. 這裡的我是指 Ting 就不是 kuku。

在 JavaScript 中,this 的工作原理類似,this 指的是它所屬的對象,它的值會根據它的使用方式和位置而改變,也就是 this 的價值取決於使用環境也就是所謂的作用域,例如一樣是 kuku,在公司身分轉換成員工;在 7-11 身分轉換成消費者,類似這樣的身分改變。

this 的不同場景

  • 在方法中
    在物件的方法中,this 指的是該物件。就像在自我介紹的時候,當有人說「我」時,他們正在介紹的是他們自己。

    const sayHello = {
        name: "kuku",
        city: "taichung",
        greet: function () {
            console.log('sayHello_this::', this);
            console.log(`Hello, ${this.name}`);
        }
    };
    

    console.log

    🔔 回顧:
    第 4 天:函式 function,提到的箭頭函數沒有自己的 this,它們是從父層作用域繼承這些值的。
    範例對照說明
    console.log

  • 單獨
    單獨使用時,this 指的是全域物件。在瀏覽器中,這通常是 window 物件。

    function sayHiAgain() {
        console.log(this);
    }
    
    sayHiAgain();
    

    console.log

    🔔 透過 F12 source 看一下全域物件是什麼?
    可以在程式碼後面加上 debugger,執行後可以打開除錯工具,在 Sources 的頁面有以下訊息
    source

  • 在常規函數中
    常規函數中的 this 指的是全域物件(在非嚴格模式下)或未定義(在嚴格模式下)。

    MDN文件:Strict mode

    "use strict";
    
    function sayHi() {
        console.log(`Hi, ${this}!`);   // "Hi, undefined!"
    }
    
    sayHi();
    

    source

  • 在事件處理程序中
    在事件處理程序中,this 指的是接收事件的元素。

    <button type="button" id="myButton" class="warning square m-1">Click me</button>
    
    document.getElementById('myButton').addEventListener('click', function (event) {
        console.log(`Button clicked by ${this.innerText}`);   // Button clicked by Click me
    });
    

    source

  • 建構函數
    在建構子內,this 指的是正在建構的物件的新建立實例。

    function Person(name) {
      this.name = name;
    }
    
    const kuku = new Person("Kuku");
    
    console.log(kuku.name);   // Kuku
    

this 的綁定


this 的綁定是指確定 this 在函數或方法內部指向哪個對象(全局、物件方法、建構子)。

function showThis() {
  console.log(this);
}
showThis(); // 在全局上下文中,`this` 指向全局對象(在瀏覽器中是 window)

const obj = {
  method: function() {
    console.log(this);
  }
};
obj.method(); // 在物件方法中,`this` 指向物件本身

前面說明 this 的調用,這裡要來說說 this 的綁定除了函數調用、物件調用,還可以使用 .call(), .apply(), 和 .bind()

.call()

MDN 文件:Function.prototype.call

call 使用給定的 this 值和單獨提供的參數來呼叫函數。

function greet(greeting, punctuation) {
  console.log(`${greeting}, ${this.name} ${punctuation}`);
}

const person = { name: "kuku" };

// person 是指定的 this 值,也就是 this 將指向 person 物件
greet.call(person, "Hello", " ◕‿‿◕ ");   // "Hello, kuku  ◕‿‿◕ "

.apply()

MDN 文件:Function.prototype.apply()

applycall 類似,但參數以數組形式提供。

語法: functionName.apply(thisArg, [argsArray])

function greet(greeting, punctuation) {
  console.log(`${greeting} , ${this.name} ${punctuation}`);
}

const person = { name: "kuku" };

// person 作為 this 上下文被傳遞進去,因此在 greet 函數內部,this 會指向 person 物件
greet.apply(person, ["Hi", "❛◡❛✿"]);   // "Hi , kuku ❛◡❛✿"

.bind()

MDN 文件:Function.prototype.bind()

bind 建立一個新函數,在呼叫函數時,將其 this 關鍵字設定為提供的值,並在呼叫新函數時在提供的任何參數之前提供給定的參數序列。

語法: const newFunction = functionName.bind(thisArg, arg1, arg2, ...)

function greet(greeting, punctuation) {
  console.log(`${greeting}, ${this.name} ${punctuation}`);
}

const person = { name: "kuku" };
// bind 方法創建了一個新的函數,這個函數會綁定 this 上下文為 person,並且預先設置了第一個參數 greeting 的值為 "Hey"
const greetPerson = greet.bind(person, "Hey");

greetPerson("๑• . •๑");   // "Hey, kuku ๑• . •๑"

總結


  • 全域:不要用就對了

    • 直接呼叫(前方無物件)、callback function、立即函式

    • use strict

      MDN文件:Strict mode

  • 作為物件:函式內的 this 是指向函式前方的物件

    🔔 this 的指向在於如何呼叫它

  • 箭頭函式:箭頭函式沒有自己的 this(指向其作用域的 this)

  • new 建構子:新建立的物件傳入函式作為 this

  • bind(), apply(), call()(強制綁定 this)


上一篇
第 16 天:建構子函數
下一篇
第 18 天:閉包與作用域
系列文
30天 JavaScript 提升計畫:從零到精通結合2024年的創新功能30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言