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
複製程式碼
情況四 apply,call,bind 呼叫
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
}.apply(a),100);
}
};
a.func2() // Cherry
複製程式碼
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout(function () {
this.func1()
}.call(a),100);
}
};
a.func2() // Cherry
複製程式碼
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
複製程式碼