javascript中this的理解
1、在函式中執行,分嚴格模式和非嚴格模式
非嚴格模式
非嚴格模式 嚴格模式 "use strict" function func(){ function func(){ console.log(this); console.log(this); } =====》 } func() //this指向window func() //this指向undefined
2、作為物件的方法被呼叫,
作為物件的方法被呼叫時:
var obj = {
name: '小賀',
sayName: function(){
console.log(this.name);
}
}
obj.sayName(); //會打印出小賀,this指向obj
將物件的方法,賦值給一個變數被呼叫。
var obj = { name: '小賀', sayName: function(){ console.log(this); } } var test = obj.sayName; test(); //this指向window
3、作為建構函式被呼叫
在呼叫一個建構函式的時候加上 new 這個關鍵字:
function Person (name) {
this.name = name;
console.log( this );
}
var p1 = new Person('kk'); //此時,this 指向這個建構函式呼叫的時候例項化出來的物件。
建構函式其實也是一個函式,若將建構函式當做普通函式來呼叫,this 指向 Window
function Person (name) { this.name = name; console.log(this); } var p2 = Person('MM'); //當前的this指向window
4、在定時器中呼叫時,this指向window
setTimeout(function(){
console.log(this); //this指向window
},0)
在沒有特殊指向時,setTimeout和setInterval的回撥函式中的this都是指向window。這是因為JS定時器都是定義在window下的。
5、在箭頭函式中的this
1)、箭頭函式實在全域性的作用域下呼叫的。this指向window.
var func = () => {
console.log(this);
}
func(); //this指向window
2)、箭頭函式作為物件的一個函式被呼叫時,this指向window。
var obj = {
name: 'koga',
func : () => {
console.log(this);
}
}
obj.func() //this 指向 window
3)、結合定時器呼叫時。
var obj = {
name: 'koga',
func: function(){
setTimeout(function(){
console.log(this);
},0)
}
}
obj.func(); //this指向window
var obj = {
name: 'koga',
func: function(){
setTimeout(() => {
console.log(this);
},0)
}
}
obj.func(); //this指向obj
在物件的函式中,普通函式作為定時器的回撥方法執行時,this指向window。箭頭函式作為定時器的回撥方法執行時,this指向定義時所在的物件。
箭頭函式中 this 的值取決於該函式外部非箭頭函式的 this 的值,且不能通過 call() 、 apply() 和 bind() 方法來改變 this 的值。
6、call、apply、bind
func.call(thisArg,arg1,arg2,arg3);
這樣會立即執行函式func,thisArg是指定執行函式中的this的上下文,後邊的都是執行該函式的引數。
func.apply(thisArg,[array])
會立即執行函式func,thisAgr是指定執行函式中的this的上下文。後邊是執行該函式的引數,它是一個數組。
func.bind(thisArg,arg1,arg2,arg3,arg4)
它不會立即執行,而是返回一個新函式,這個心函式被指定了this的上下文,後邊的是執行該函式時傳入的引數。
function Person (name, age) {
this.name = name;
this.age = age;
console.log(this);
}
var obj = {
name: 'kk' ,
age: 6
};
Person.call(obj, 'mm', 10 );
// obj,{name: "mm", age: 10}
Person .apply(obj, ['mm',10]);
// obj,{name: "mm", age: 10}
var p1 = Person.bind(obj, 'mm', 10)
var p2 = new p1();
// Person {name: "mm", age: 10}
在這個示例中,call、apply 和 bind 的 this 都指向了 obj,都能正常執行;call、apply 會立即執行函式,call 和 apply 的區別就在於傳遞的引數,call 接收多個引數列表,apply 接收一個包含多個引數的陣列;bind 不是立即執行函式,它返回一個函式,需要執行 p2 才能返回結果,bind 接收多個引數列表。
7、如何修改this的指向。
1)、使用箭頭函式修改this的指向。
var obj = {
name:'koga',
func1: function(){
console.log(this.name);
},
func2: function(){
setTimeout(function(){
this.func1();
})
}
}
這時會報錯,因為這是setTimeout中的this指向的是window,而在window上並未定義func1方法。
var obj = {
name:'koga',
func1: function(){
console.log(this.name);
},
func2: function(){
setTimeout(() => {
this.func1();
})
}
}
這時不會報錯,箭頭函式的this取決於該函式外邊的非箭頭函式的this的指向。也即是func2中的this的指向,即obj。
2)在函式中使用_this = this
var obj = {
name:'koga',
func1: function(){
console.log(this.name);
},
func2: function(){
var _this = this;
setTimeout(function(){
_this.func1();
})
}
}
此時,func2 也能正常執行。在 func2 中,首先設定 var _this = this,這裡的 this 是指向 func2 的物件 obj,為了防止在 func2 中的 setTimeout 被 window 呼叫而導致的在 setTimeout 中的 this 為 window。我們將 this (指向變數 obj) 賦值給一個變數 _this,這樣,在 func2 中我們使用 _this 就是指向物件 obj 了。
3)、使用call 、apply、bind等方法改變this的指向。