2014-04-16 34 views
1

我很抱歉問這樣一個基本的問題,但儘管過去幾個月在javascript上有很多的閱讀和特別是在這個問題上,我只是沒有得到它是執行上下文和「this」。所以我希望使用我的具體情況的解釋會有所幫助。我有一個構造函數,其中有一些本地函數和一些公開的函數(模仿public/private方法)。順序函數調用的執行上下文 - 這改變到窗口

function blog() { 
    if (!(this instanceof blog)) 
     return new blog(); 

    function internal(){ 
     alert(this); 
    } 

    this.external = function(){ 
     alert(this); 
     internal(); 
    } 
} 

var b = new blog(); 
b.external(); 

external, 「本」 是B,博客的一個實例,如我所料。我錯誤地認爲這在internal中也是如此,但它實際上是全局窗口對象。作爲一個實驗,我試着改變external的號碼this.internal(),這給出了this.internal不是函數的錯誤。這是當我意識到我真的沒有遵循它的工作原理。好的,我沒有定義名爲internal的博客屬性,但是如果internal不是我博客實例上定義的函數,它是什麼以及它在哪裏定義的?也許我有這個結構錯誤。

+0

這可能重複:http://stackoverflow.com/questions/2719643/javascript-this-points-to-window-object 這一次似乎是一個更好的例子:http://stackoverflow.com/questions/12241696/why-the-code-this-point-to-window-object –

+0

參見https://developer.mozilla.org/en-US/docs/Web/JavaScript /參考/運營商/這和http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback。 –

回答

0

請參閱xdazzs這裏回答:https://stackoverflow.com/a/12241726/2469255

但是,解決你的問題,你需要定義什麼this是該功能。

調用內部調用時未提供此上下文,因此它將綁定到全局對象,而不像this.external已將其範圍限定爲博客對象。重寫你的代碼如下會解決這個問題:

function blog() { 
    if (!(this instanceof blog)) 
     return new blog(); 

    function internal(){ 
     console.log(this); 
    } 

    this.external = function(){ 
     console.log(this); 
     internal.bind(this); 
     internal.call(this); // this in internal will be the object blog. 
    } 
} 

var b = new blog(); 
b.external(); //blog {external: function} blog {external: function} 

或者很多人喜歡var self = this,以確保這樣的問題不會發生,你確切地知道什麼東西被設置在哪裏。這個特殊的想法有很多爭議,所以YMMV

+0

閱讀該鏈接後我更加困惑。代碼過於複雜。但是,除了使用我的代碼示例外,這是我正在尋找的那種答案的一個很好的例子。我明白*它正在做什麼,我可以使用call/bind/apply來修改「this」,但不是它爲什麼要這樣做。實際上我甚至不需要在我的「內部」中使用「this」,所以一切正常,我只是想了解JS的行爲。那麼你是否說任何函數調用默認爲窗口,除非你另有說明? 'internal'功能是否屬於'blog'或窗口? – xr280xr

+1

@ xr280xr:這是'blog'內的本地函數。 'this'指的是'window',因爲你把這個函數調用爲'internal()'。請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#Simple_call。 'this'的值只取決於函數的調用方式。 –

+0

謝謝@Felix,很好的鏈接。我想我現在明白了。也許這比我想象的更簡單。讓上下文與函數定義的範圍無關,感覺很奇怪!所以我不能調用'this.internal()',因爲它不是'blog'的屬性,但是我可以調用'internal()',因爲它與'external'創建的範圍相同,對嗎?封閉? – xr280xr

0

讓我試着解釋一下。

這段代碼將只能到達,如果你簡單地撥打blog()沒有new關鍵詞。

if (!(this instanceof blog)) 
    return new blog(); 

但是,這不是一個推薦的實踐,因爲它影響你的代碼清晰。

正因爲如此:

var realObj = new Blog(); 

是實例化對象和波紋管代碼正確代碼:

var obj = blog(); 

都不夠清楚,可以指導你的錯誤。

JavaScript原本是一個原型繼承,您可以從Douglas Crockford更好的解釋here

internal()external沒有相同參考的主要原因是內部有一個指向全局的範圍,當您創建博客實例時,外部範圍指向對象博客。

真的很迷惑,因爲this裏面的博客都是指向全局的,所以爲什麼當你實例化博客this更改?

當瀏覽器開始讀取您的代碼時,它會將它在內存中找到的內容引用到範圍內。記住範圍是由{}控制的,所以當他發現你的聲明this.external他與範圍相關聯,並且當你聲明使用newthis成爲該對象的範圍,因此this不再引用全局範圍。

看看這個code在jsbin.com

+0

我看不到這些代碼會如何產生堆棧溢出。如果我運行'new blog()',它會創建一個實例。 ';(!(這個instanceof博客))返回新的blog();''通常你用來做'blog()'(即調用沒有'new'關鍵字的函數)作爲'new blog()'。並且你談論了很多關於* scope *的內容,但是這個''如何運作並沒有任何*與範圍有關。 –

+0

是的,你是對的,但這不是推薦實踐。 –

+1

說誰?這是實現該模式的一個非常簡單的解決方案。但除此之外,這與OP的問題無關。 –