請說明要輸出正確的myName的值要如何修改程序?並解釋緣由
foo = function(){ this.myName = "Foo function."; } foo.prototype.sayHello = function(){ alert(this.myName); } foo.prototype.bar = function(){ setTimeout(this.sayHello, 1000); } var f = new foo; f.bar();
先跟蹤一下函數的執行。windows
全局環境下,聲明一個變量,實例化foo賦值給f,函數未執行。打印f,結果是:app
很顯然,f就是一個foo的副本,它是一個對象,副本內部的函數就是該對象的方法,能夠點式調用。foo是函數不能夠直接做爲對象調用內部方法。函數
console.log(typeof f); //object
console.log(typeof foo); //functionthis
tips:函數foo內部聲明的屬性或方法前加this目的在於保護變量同時能夠被實例化的對象訪問,若是直接聲明私有變量,沒法實例化後使用,而若成爲全局變量又可能形成污染。好比去掉setTimeout前的this,那麼sayHello變成了全局變量,而若全局中未聲明這個函數,就會形成錯誤。spa
console.log(f.name);//Foo functionprototype
對象f調用bar以後,被賦值的函數執行,this指向這個對象,而後setTimeout開始執行,指向window,f的方法sayHello在5s後被調起,此時它處在windows環境中,所以alert(this.myName)會嘗試去window環境獲取這個值。以下:3d
var myName = "江太公";
//or this.myName = "江太公";
function sayHello(){alert("江太公");}
foo = function(){
this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){
alert(this.myName);
}
foo.prototype.bar = function(){
setTimeout(this.sayHello, 5000);
}
var f = new foo;
console.log(f);
f.bar();
console.log(f.bar);
console.log(foo.bar);
console.log(typeof f);
console.log(typeof foo);
// console.log(f.myName);code
結果彈出:江太公。證明個人想法。對象
ok,整個執行流程很簡單,但中間的this轉換可能讓人困惑。下面給出這道題的4種解決方案。blog
方案一:用bind對this進行轉向。
foo = function(){
this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){
alert(this.myName);
}
foo.prototype.bar = function(){
setTimeout(this.sayHello.bind(this), 5000);
}
var f = new foo;
f.bar();
方案二:用call/apply進行轉向。
foo = function(){
this.myName = "Foo function.";
}
foo.prototype.sayHello = function(){
alert(this.myName);
}
foo.prototype.bar = function(){
setTimeout(this.sayHello.apply(this), 5000);
}
var f = new foo;
f.bar();
方案三:用that進行hack。
foo = function(){ this.myName = "Foo function."; } foo.prototype.sayHello = function(that){ alert(that.myName); } foo.prototype.bar = function(){ var that = this; setTimeout(function(){that.sayHello(that);}, 5000); } var f = new foo; f.bar();
方案四:使用箭頭函數。
foo = function(){ this.myName = "Foo function."; } foo.prototype.sayHello = function(){ alert(this.myName); } foo.prototype.bar = function(){ setTimeout(()=>{this.sayHello()}, 5000); } var f = new foo; f.bar();
或者:
foo = function(){ this.myName = "Foo function."; } foo.prototype.sayHello = ()=>{alert(this.myName)}; foo.prototype.bar = function(){ setTimeout(this.sayHello, 1000); } var f = new foo; f.bar()
方法五:還有一種特特簡單的辦法,將構造函數的this也轉向到全局。
foo = function(){ this.myName = "Foo function."; } foo.prototype.sayHello = function(){ alert(this.myName); } foo.prototype.bar = function(){ setTimeout(this.sayHello, 1000); } var f = new foo; foo(); f.bar()
發現其餘途徑煩請告我一聲,謝謝。