結論 不多說,想給出結論 關於this到底指向誰這個問題,我很同意鳥哥給出這麼一個結論 ”This關鍵字永遠都指向函數(方法)的所有者” (參考文章1). 作為函數調用時 直接調用函數屬於全局性調用,因此this指向全局對象(window對象),this.name為"global"。 作為構造函數調
結論
不多說,想給出結論 關於this到底指向誰這個問題,我很同意鳥哥給出這麼一個結論 ”This關鍵字永遠都指向函數(方法)的所有者”(參考文章1).
作為函數調用時
var name="global";
function showname(){
alert(this.name);
}
//global
直接調用函數屬於全局性調用,因此this指向全局對象(window對象),this.name為"global"。
作為構造函數調用時
var name="global";
function People(name){
this.name=name;
}
var p = new People('people');
alert(name);
//global
alert(p.name);
//people
JavaScript很特殊,並沒有類的概念,JavaScript中的構造函數也很特殊,如果不使用new調用,則和普通函數一樣,為了跟上一種情況區別,分別alert全局的name和新創建的對象p的name,可以看出this指向構造函數的所有者--新創建的對象p。
作為對象方法調用時
var name="global";
var people={
name:"obj",
showname:function(){
alert(this.name);
}
};
people.showname();
// obj
showname作為people的方法調用時,方法的所有者為people,所以this.name為people的name屬性"obj"。
DOM事件
//DOM
<input id="dom" type="text" value="dom" onblur="showthis()"/>
//JS
var value="global";
function showthis(){
console.log(this.value);
}
//global
這個輸出沒什麼問題,跟上面的直接調用函數,this指向全局,但是我們看下麵一種寫法
//DOM
<input id="dom" type="text" value="dom" />
//JS
var value="global";
function showthis(){
console.log(this.value);
}
//dom
這是為什麼呢?在Js中一切都是對象,原來在對onclick綁定處理器的時候, 其實是對id為dom的輸入框Dom對象的onclick屬性賦值.所以showthis的所有者是id為dom的輸入框Dom對象,所以this.value為"dom"。
改變this指向
apply()/call()
在 JavaScript 中函數也是對象,apply和call就是函數對象的方法。他們允許改變this關鍵字的指向。
javascript var name="global"; function showname(){ alert(this.name); } var people={}; people.name="people"; people.showname=showname; people.showname.apply(people); //people people.showname.apply(); //global
apply(call)的第一個參數就表示改變後的調用這個函數的對象,所以people.showname.apply(people);this指向函數所有者people對象,所以第一次輸出為people,apply()的參數為空時,預設調用全局對象,所以第二次輸出為global。
bind()
bind() 最簡單的用法是創建一個函數,使這個函數不論怎麼調用都有同樣的 this 值。JavaScript新手經常犯的一個錯誤是將一個方法從對象中拿出來,然後再調用,希望方法中的this是原來的對象。(比如在回調中傳入這個方法。)如果不做特殊處理的話,一般會丟失原來的對象。
通常,bind()配合 setTimeout()使用:
在預設情況下,使用 window.setTimeout() 時,this 關鍵字會指向 window (或全局)對象。當使用類的方法時,需要 this 引用類的實例,你可能需要顯式地把 this 綁定到回調函數以便繼續使用實例。
function LateBloomer() {
this.petalCount = 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
window.setTimeout(this.declare, 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
//I am a beautiful flower with 1 petals!
//I am a beautiful flower with undefined petals!