2017-02-21 101 views
0

我曾經認爲所有參數和命名函數都不在函數內部,應該在全局上下文中註冊(在'this'上下文中),但下面的代碼讓我感到困惑。變量不會在全局上下文中註冊,爲什麼?

爲什麼沒有關鍵字var的變量可以在'this'上下文中註冊,而其他的不可以?

g_var_1 = "I'm in the global context"; 
var g_var_2 = "I'm not in the global context"; 

function g_func() { 
    console.log("why I'm not in the global context?"); 
} 

(function() { 
    console.log(this);   //do not see g_var_2 and g_func 
})(); 

//test the global context variables 
(function() { 
    console.log(this.g_var_1); //ok 
    console.log(this.g_var_2); //undefined 
    console.log(g_var_1);  //ok 
    console.log(g_var_2);  //ok 
    this.g_func();    //Error 
    g_func();     //ok 
})(); 
+2

您應該在嚴格模式下編碼,其中沒有隱式全局變量,並且沒有'this'的意外值。這些都是JavaScript的原創設計師所做的可怕事情,他們試​​圖隨着時間的推移來擺脫它。然後一個變量將只存在於你聲明它的範圍內,以及任何可以看到它的子範圍。而且,「這個」根本就沒有價值,除非你明確地讓它具有特定的價值。所以,不會有事故發生,並且不會發生事故而造成麻煩。嘗試以嚴格模式運行您的代碼。 – jfriend00

+0

感謝您的回覆,我只想弄清楚這是如何工作的。 – user1726366

回答

1

首先,因爲它被標記爲node.js,您應該認識到node.js中包含的所有代碼都包含在其中的node.js模塊實際上是在一個函數內部。

每個Node.js的模塊包裹裏面的東西是這樣的:

(function (exports, require, module, __filename, __dirname) { 
    // Your module code actually lives in here 
}); 

所以,你聲明在Node.js的模塊中的頂級範圍的東西其實並不是在頂部範圍 - 這是一個內部包裝功能。其次,這個問題只能通過討論嚴格模式和非嚴格模式來解決。由於看起來你可以運行你的代碼,你必須以非嚴格模式運行它。爲此,您將得到以下規則:

  1. 您分配給的任何非聲明變量都變爲隱式全局變量。
  2. 您調用的任何普通函數都將指向全局對象的指針this

所以,現在用這兩個規則,讓我們來看看結果:

g_var1成爲一個全球性的。

g_var2不是全球性的。它在模塊範圍中明確聲明,如上所述,它不是最高級別。它在模塊函數包裝器中。

g_func同樣不是全球性的。這是一個模塊級功能。

然後,當你這樣做:

(function() { 
    console.log(this);   //do not see g_var_2 and g_func 
})(); 

this的值設置爲global對象,你沒有看到g_var_2g_func,因爲正如我剛纔所說,他們不是全局的,但有模塊範圍。

然後,當你運行這個命令:

//test the global context variables 
(function() { 
    console.log(this.g_var_1); //ok 
    console.log(this.g_var_2); //undefined 
    console.log(g_var_1);  //ok 
    console.log(g_var_2);  //ok 
    this.g_func();    //Error 
    g_func();     //ok 
})(); 

this被設置爲全局對象。 g_var_1是一個真正的全球所以this.g_var_1的作品。由於g_var_2g_func不是全局符號,因此它們都不能通過this來引用。

但是,g_var_1g_var_2g_func的全部都在父範圍內,因此您可以自行引用它們就好了。


現在,讓我們來談談如何在strict模式下編程。 strict模式是JavaScript努力擺脫它出生的可怕事物的語言,自動將未聲明的變量變成全局變量,並自動將this的值設置爲普通函數中的全局對象。這兩件事導致許多意外錯誤,其中代碼報告沒有錯誤,但由於輕微的輸入錯誤而沒有按照您的意圖執行。

因此,在strict模式下,如果您嘗試使用您尚未聲明的變量,則會立即發生錯誤(邏輯是應該修復該問題)。並且,在常規函數內,this的值是undefined

所以,在你的計劃:

分配給g_var_1將立即導致錯誤。您必須將其聲明爲全局變量或模塊變量才能使用它。其他變量是聲明的,所以它們的範圍保持不變。

,在這裏面:

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

this的價值將是undefined。然後,在這裏:

//test the global context variables 
(function() { 
    console.log(this.g_var_1); //ok 
    console.log(this.g_var_2); //undefined 
    console.log(g_var_1);  //ok 
    console.log(g_var_2);  //ok 
    this.g_func();    //Error 
    g_func();     //ok 
})(); 

this將是不確定的所以沒有從它引用的正常工作。通常聲明的變量按預期工作。

+0

優秀的解釋,謝謝! :) – user1726366

+0

@ user1726366 - 我添加了嚴格的模式說明。 – jfriend00

+0

@ jriend00羅傑。 :) – user1726366

0

因爲當你你聲明它是全球變種的名稱前使用「變種」。然後,如果要重新聲明該變量,例如,在函數內部,則將'var'放在該函數內的名稱之前。

相關問題