回到文章列表

[JS201 筆記] 先學完物件導向,學 this 才有意義

TWGD / 2019-01-08

這是 Lidemy 課程:[JS201] 進階 JavaScript:那些你一直搞不懂的地方:先學完物件導向,學 this 才有意義 課程筆記。

如果有人不小心看到,請不要太嚴格,這只是我上課的隨筆筆記XD 若有錯誤,請不要吝嗇糾正我,謝謝~


this 的意義?

this 在物件導向裡面使用,意義是指向指定的 instance。

非物件導向下的 this 預設值是什麼?

在不同環境底下,預設值不同 ( 非嚴格模式 ):

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

test();
// node.js 裡面,this 是 global
// 在瀏覽器裡面,this 預設是 window

嚴格模式:

'use strict'; // 加上這段程式碼,使用嚴格模式

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

test(); // undefined
// 在 node.js 或瀏覽器,this 都是 undefined

dom 操作的 this:

document.querySelector('.btn').addEventListener('click', function() {
    console.log(this);
})
// 結果會是 click 的對象

用 call 與 apply,呼叫 function:

用法:

func.call(context, p1, p2, p3);
// 第一個參數傳的值就是 this
// 後面依序傳 func 的參數

func.apply(context, [p1, p2, p3]);
// 只接收兩個參數
// 第一個參數傳的值就是 this
// 第二個參數傳一個 func 的參數陣列
'use strict';

function test(a, b, c) {
    console.log(this);
    console.log(a, b, c);
}

test.call(123, 1, 2, 3);
// 123
// 1 2 3

test.apply(123, [1, 2, 3]);
// 123
// 1 2 3

call() 與 apply() 的差異:

  • call():從第二個參數開始,依序傳入 function 的參數。
  • apply():只接收兩個參數。第二個參數傳一個 function 的參數陣列。
  • 強制綁定 this:bind

    強制綁定之後,無論用什麼呼叫方法,this 都不會改變。

    'use strict';
    
    const obj = {
        a: 123,
        test: function() {
            console.log(this);
        }
    }
    
    // 強制綁定:bind() 裡面傳什麼,this 就會是什麼
    const bindTest = obj.test.bind(obj);
    bindTest(); // 印出的會是 obj
    bindTest.call('hahaha'); // 印出的還是 obj
    bindTest.apply('lalala'); // 印出的依然是 obj
    

    bind() 與 call()、apply() 的差異:

  • bind():綁定好之後,回傳一個 function
  • call()apply():直接呼叫 function。
  • arrow function 的 this

    特別注意:arrow function 的 this 與呼叫的方法沒有關係,只與『如何定義』有關係。 this 的值會是定義 function 那個地方的 this 值。

    比較:

    class Test {
        run() {
            console.log('run test:', this);
            setTimeout(function() { // 這裡使用 function(){}
                console.log(this);
            }, 100);
        }
    }
    
    const t = new Test();
    t.run();
    // run test: Test {}
    // window (瀏覽器預設值)
    
    class Test {
        run() {
            console.log('run test:', this);
            setTimeout(() => { // 這裡使用 arrow function
                console.log(this);
            }, 100);
        }
    }
    
    const t = new Test();
    t.run();
    // run test: Test {}
    // Test {}