this

Node.js this

this 是什麼

  • this 是 JavaScript 的一個關鍵字。
  • this 是 function 執行時,自動生成的一個內部物件。
  • 隨著 function 執行場合的不同,this 所指向的值,也會有所不同。
  • 在大多數的情況下, this 代表的就是呼叫 function 的物件。
  • 非物件導向底下,要看執行環境有不同預設值
    • node.js : global
    • 瀏覽器 : window
    • 嚴格模式 : undefined ( node.js 跟瀏覽器都一樣 )
  • 物件導向中, this 就是 new 出來的 instance
  • DOM 事件綁定時, this 為 綁定的 DOM 物件
  • 單純在物件底下,this 跟如何呼叫 function 有關
  • 如果是在物件本身上呼叫,this 為物件本身
  • 把 function 抽出來呼叫,this 則為預設值 ( global or window or undefined )
  • arrow function 中,根據外部的 this 是什麼而決定
var obj = {

    func1: function(){
        // 這裡的 this 指的是 func1
        // [func1] is object: true
        console.log( '[func1] is object:', this === obj );

        var func2 = function(){
            // 這裡的 this 指的是 global
            // [func2] is obj:  false
            console.log( '[func2] is obj: ', this === obj );
            // [func2] is global true
            console.log( '[func2] is global', this === global );
        };

        func2();
    }
};

obj.func1();

func1 透過 object 呼叫,所以裡面的 this 指的是 obj 物件本身

func2 直接呼叫,沒特別指定的話,指的就是全域變數 global

function 透過物件呼叫及直接呼叫

function func() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: func
};

// undefined
func();
// 2
obj.foo();    

透過物件呼叫,因為裡面的 this 指的會是物件本身,所以能夠取的物件的 屬性 a 資料

var a = {
    value : 1,
    getVal: () => this.value
};

var b = {
    value : 2,
    getVal: function () {
        return this.value
    }
}

// undefined
console.log(a.getVal());
// 2
console.log(b.getVal());

var c = a.getVal;
var d = b.getVal;

// undefined
console.log(c());
// undefined
console.log(d()); 
function func() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: func
};

// 2
obj.foo();  

var func2 = obj.foo;
// undefined
func2();

func2 參照的對象是 global 所以還是無法存取到 屬性 a 資料

變更 this 對象

透過 bind, call, apply 可以變更 this 指定對象

function func() {
    console.log( this.a );
}

var obj = {
    a: 2,
    foo: func
};

// 2
obj.foo();

var func2 = obj.foo;
// undefined
func2();

let bindFunc2 = func2.bind(obj)
// 2
bindFunc2();
// 2
func2.apply(obj);
// 2
func2.call(obj);

使用 new 會建立屬於該函式的物件

function foo(a) {
    this.a = a;
}

var obj = new foo( 123 );
// 123
console.log( obj.a );

this 來源

執行方式 this 指的是
使用 new 建立 被建構的物件
使用 bind, call, apply 傳入的物件
function 被呼叫是否存在某物件 存在的物件
其他 全域物件 global (嚴格模式則為 undefined)

例外狀況

箭頭函示 arrow function 中的 this

箭頭函式當中的 this 綁定的是是定義時的物件,而不是使用時的物件,所以定義當下 this 指的是哪個物件就會是那個物件,不會隨著時間改變

Example 1: 一般函式
'use strict';

class Test {
    run() {
        console.log('run: ', this);
        setTimeout(function() {
            console.log('setTimout: ', this);
        }, 1000);
    }
}
const test = new Test();
test.run();
// run: Test {}

// setTimout:  Timeout {
//   _idleTimeout: 1000,
//   _idlePrev: null,
//   _idleNext: null,
//   _idleStart: 43,
//   _onTimeout: [Function (anonymous)],
//   _timerArgs: undefined,
//   _repeat: null,
//   _destroyed: false,
//   [Symbol(refed)]: true,
//   [Symbol(kHasPrimitive)]: false,
//   [Symbol(asyncId)]: 5,
//   [Symbol(triggerId)]: 1
// }
Example 2: 箭頭函式
'use strict';

class Test {
    run() {
        console.log('run: ', this);
        setTimeout(() => {
            console.log('setTimout: ', this);
        }, 1000);
    }
}
const test = new Test();
test.run();
// run: Test {}
// setTimout: Test {} ( 一秒後 )

事件監聽中的 this

DOM 物件綁定某種事件時,this 會變成綁定的 DOM 元素本身

document.querySeletor('.btn').addEventListener('click', function(){
    console.log(this); // => btn 這個元素
});

參考資料