javascript中this的指向問題
阿新 • • 發佈:2019-01-06
this 指的是當前物件,如果在全域性範圍內使用this,則指代當前頁面window;如果在函式中使用this,則this指代什麼是根據當前函式是在什麼物件上呼叫。我們可以使用call和apply改變函式中this的具體指向。另外,在建構函式或者建構函式原型物件中this指向建構函式的例項。
1.全域性作用域或者普通函式中this指向全域性物件window。
console.log(this === window) // true
console.log(window.alert === this.alert) // true
console.log(this.parseInt("051",10)) // 51
注意:全域性作用域中函式中的this,在嚴格模式下,這種函式中的
this
等於undefined
"use strict";
console.log("嚴格模式");
console.log('在全域性作用域中函式中的this');
function f1(){
console.log(this);
}
function f2(){
function f3(){
console.log(this);
}
f3();
}
f1();//undefined
f2();//undefined
2.函式中的this是在執行時候決定的,而不是函式定義時。
function boy(){
console.log(this.man);
}
// 定義一個全域性變數,等同於window.man = "Tom";
var man= "Tom";
// 此時函式中的this指向window;
boy(); // "Tom"
var b = {
man : "Jim",
boy: boy
};
// 此時函式中的this指向物件 b
b.boy(); // "Jim"
全域性函式apply和call可以用來改變this的指向,如下:
function boy(){
console.log(this.man);
}
// 定義一個全域性變數,等同於window.man= "Tom";
var boy= "Tom";
var b = {
man: "Jone"
};
boy.apply(window); // "Tom";
boy.call(b); // "Jone";
apply的引數需要放在一個數組裡面,而call不需要,舉例:
function boy(){
if(this === window){
console.log("this is window");
}
};
// 函式boy也是物件,可以為物件定義屬性,然後屬性為函式
boy.boo = function(){
if(this === boy){
console.log("this is boy");
}else if(this === window){
console.log("this is window");
}
};
// 等價於 window.boy();
boy(); // "this is window";
// 可以看到函式中this的指向呼叫函式的物件
boy.boo(); // "this is boy";
// 可以使用call改變函式中this指向
boy.boo.call(window); // "this is window";
3.物件中的巢狀函式的this指向不是當前物件,而是window:
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return function(){
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "window.name"
要怎樣解決上述問題呢?主要有三種解決辦法,如下:
(1).使用函式的bind方法,綁定當前this;
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return function(){
console.log(this.name);
}.bind(this);
}
};
obj.getName()(); // "obj.name" "obj.name"
(2).使用變數將上面的this接收一下,然後下面不使用this,使用那個變數;
var name = "window.name";
var that = null;
var obj = {
name : "obj.name",
getName:function(){
that = this;
console.log(this.name);
return function(){
console.log(that.name);
}
}
}
obj.getName()(); // "obj.name" "obj.name"
(3).使用ES6的箭頭函式,可以完美避免此問題;
var name = "window.name";
var obj = {
name : "obj.name",
getName:function(){
console.log(this.name);
return () => {
console.log(this.name);
}
}
}
obj.getName()(); // "obj.name" "obj.name"
4.函式作為建構函式,用new關鍵字呼叫時:this指向新new出的物件
//不使用new指向window
function Man(name) {
console.log(this)
this.name = name;
}
Man('nonew');// window
//使用new
function Man(name) {
this.name = name
console.log(this)
self = this
}
var people = new Man('new') //people
console.log(self === people) //true
//這裡new改變了this指向,將this由window指向Man的例項物件people
5. 事件處理函式中的this;在嚴格模式下,在事件處理函式中,this
指向觸發事件的目標物件。
z注意:內聯事件處理
當代碼在元素上進行呼叫處理,this指向的是這個DOM元素.
<button onclick="alert(this.tagName.toLowerCase());">
Show this
</button>
上面顯示的是這個按鈕. 記住只有這種方式,返回的是這個元素.
<button onclick="alert((function(){return this}()));">
Show inner this
</button>
在這個例子中,內部函式this沒有被設定,因此它返回的全域性物件window.