iT邦幫忙

0

javascript面試考題的問題

              var Obj=function(msg){
  
                    this.msg=msg;
  
                    this.shout=function()
                    {
                      alert(this.msg);
                    };
  
                    this.waitAndShout=function()
                    {
                      setTimeout(this.shout, 2000);
                    };
        };

        var aa=new Obj("abc");        
        aa.waitAndShout();

上述是某個javascript面試的題目,debug後發現,只要在this.shout後面加上()即可正常,
我的問題是【為什麼要加上小括號】,shout才抓的到msg這個變數?

感謝

2 個回答

16
weiclin
iT邦高手 4 級 ‧ 2015-02-25 17:38:17
最佳解答

如果你是這樣子改, 那你就改錯了:

<pre class="c" name="code">
var Obj=function(msg){
    this.msg=msg;
    this.shout=function()
    {
        alert(this.msg);
    };
    
    this.waitAndShout=function()
    {
        setTimeout(this.shout(), 2000);
    };
};

var aa=new Obj("abc");
aa.waitAndShout();

就這題目而言, 應該是要等待兩秒後才顯示訊息
上面的改法會直接顯示, 不會等待兩秒

要修正的話應該這麼改:

<pre class="c" name="code">
var Obj=function(msg){
    this.msg=msg;
    this.shout=function()
    {
        alert(this.msg);
    };
    
    this.waitAndShout=function()
    {
        var _this = this;
        setTimeout(function(){_this.shout();}, 2000);
    };
};

var aa=new Obj("abc");
aa.waitAndShout();

這題目關鍵的地方在於 js 對於 this 的判定方式, 是單純看 . 號左邊是誰
所以你把 this.shout 丟進 setTimeout 裡面以後, shout 這個 function 裡面的 this 就不是 var Obj 了
你可以這樣子觀察 this:

<pre class="c" name="code">
var Obj=function(msg){
    this.msg=msg;
    this.shout=function()
    {
        alert(this);
    };
    
    this.waitAndShout=function()
    {
        setTimeout(this.shout, 2000);
    };
};

var aa=new Obj("abc");
aa.waitAndShout();

在我的瀏覽器, 它顯示 this 是 Window 這個物件
而理所當然的 Window 並沒有 .msg 這個屬性, 所以顯示 undefined

0
hungchinwai
iT邦研究生 1 級 ‧ 2015-02-26 10:58:38

可以將setTimeout用function包起來看,很明顯如果用this它將呼叫本身function,不是外部Obj物件,所以需將this儲存在Obj物件的變數裡,在由這變數呼叫function

<pre class="c" name="code">
var Obj=function(msg){
	this.msg=msg;

	this.shout=function(){
	  alert(this.msg);
	};

	this.waitAndShout=function(){
		pthis = this;
		setTimeout(function(){
			pthis.shout();
		}, 2000);
	};
};
var aa=new Obj("abc");        
aa.waitAndShout();

我要發表回答

立即登入回答