this指向

陳林007發表於2019-04-17

es5 this指向分四種情況

情況一:純粹的函式呼叫
  • 這是函式的最通常用法,屬於全域性性呼叫,因此this就代表全域性物件。
var x = 1;
function test() {
   console.log(this.x);
}
test();  // 1
複製程式碼
情況二:作為物件方法的呼叫
  • 函式還可以作為某個物件的方法呼叫,這時this就指這個上級物件。
function test() {
  console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;

obj.m(); // 1
複製程式碼
情況三 作為建構函式呼叫
  • 所謂建構函式,就是通過這個函式,可以生成一個新物件。這時,this就指這個新物件。
function test() {
  this.x = 1;
}

var obj = new test();
obj.x // 1
複製程式碼
  • 執行結果為1。為了表明這時this不是全域性物件,我們對程式碼做一些改變:
var x = 2;
function test() {
  this.x = 1;
}

var obj = new test();
obj.x  // 1

複製程式碼
  • 執行結果為1,表明全域性變數x的值根本沒變。
情況四 apply,call,bind 呼叫
  • apply
var a = {
        name : "Cherry",
        func1: function () {
            console.log(this.name)
        },
        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.apply(a),100);
        }
    };

    a.func2()            // Cherry
複製程式碼
  • call
var a = {
        name : "Cherry",
        func1: function () {
            console.log(this.name)
        },
        func2: function () {
            setTimeout(function () {
                this.func1()
            }.call(a),100);
        }
    };

    a.func2()            // Cherry
複製程式碼
  • bind
 var a = {
        name : "Cherry",
        func1: function () {
            console.log(this.name)
        },
        func2: function () {
            setTimeout(  function () {
                this.func1()
            }.bind(a)(),100);
        }
    };

    a.func2()            // Cherry
複製程式碼

箭頭函式和普通函式區別

* 沒有 this,不能改變 this 繫結
* 不能通過 new 呼叫,當然也沒有原型(prototype)
* 沒有 arguments 物件,不能有相同命名引數
* 箭頭函式雖然沒有 this ,但是還是可以在內部使用 this 的
* this 的繫結取決於定義函式時的上下文環境
* 一旦函式呼叫,任何改變 this 的方法都無效
複製程式碼

練習題

let x = 11111
let a = {
    x: 1,
    init() {
        // 箭頭函式的 this 取決於 init,所以可以列印出 1
        document.addEventListener('click', () => console.log(this.x))
    },
    allowInit: () => {
        // allowInit 直接是個箭頭函式,所以這時的 this 變成了 window
        // 但是並不會列印出 11111,使用 let 時變數也會被提升至塊級作用域的頂部,但是隻提升宣告,不提升初始化
        console.log(this.x)
    },
    otherInit() {
        // 普通函式的 this 取決於呼叫函式的位置,this 指向 document
        // 如果想列印出 x,可以使用 bind
        document.addEventListener('click', function() {
            console.log(this.x)
        })
    }
}
a.init() // -> 1
a.allowInit() // -> undefined
a.otherInit() // -> undefined
複製程式碼

相關文章