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;
// 相似這種寫法
var obj = {
x:"1",
m: function() {
console.log(this.x);
}
}
console.log(obj.m())
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
複製代碼