2013-03-08 95 views
5

在任何Web瀏覽器中執行以下腳本將導致'wee'被髮送到控制檯。在節點中,它發送{}vars在Nodejs中存儲在哪裏?

var d = 'wee'; 
console.log(this.d); 

我意識到,在節點this指的是在這種情況下的導出對象。我知道global變量,這不是我想要訪問的。此外,上面的腳本也沒有在全局對象上設置d。它到底在哪裏?在上面的腳本中,我可以通過console.log(d);明確地訪問它,但它似乎在一些非標準空間中隱藏起來,沒有任何理由。

我也意識到,去掉varglobal對象,這是預期的行爲雖然看起來愚蠢有var在頂層範圍存儲在不同的地方比「裸」變量及其值上宣佈d。我的意思是,模塊系統應該是防止全球污染的一種數字預防措施嗎?在這裏,打破模式似乎很容易,而且做一些標準工作很困難。

d也未在module對象上聲明。

我不必證明爲什麼我會問這個問題,但我會回答第一個巨魔來與「但你爲什麼想要做durrrr」。

var d = {}; 
d.bleep = 'y'; 
var a = Object.keys(d); 

d.bloop = 'y'; 
d.blop = 'y'; 

var b = Object.keys(d); 

// c = b - a; 
var c = b.filter(function (item) { 
    if(a.indexOf(item) === -1) { 
     return true; 
    } 
    return false; 
}); 

console.log(a,b,c); 

在我能的d特定對象狀態之間進行區分以同樣的方式,我應該能夠區分頂層範圍的狀態。在瀏覽器中,這是window對象,在頂層範圍內由this引用。我應該能夠在腳本執行之前和之後評估環境的屬性,以確定很多事情,其中​​之一是檢查在任意腳本的頂部範圍內聲明的函數和變量,然後可以將它們應用於導出對象。這將可以很容易地編程生成其不與應用的頂層函數和變量列表中指定whateverThisIs['varFunc']module.exports['varFunc']簡單forEach寫成模塊腳本模塊封裝...

和東西...

此行爲看起來像一個匿名函數。在一個匿名函數中,this可能指的是window對象,var將不得不直接調用(因爲它們在anon func的作用域中),沒有var關鍵字的聲明的泄漏變量可能會在window對象處結束。我還沒有閱讀整個手冊,也許這正是發生了什麼,但是,我的印象是,每個模塊在自己的上下文(窗口)中執行,並且節點通過使用global在模塊上下文之間傳遞消息,以及module.exports ...

我不知道。但我想知道。如果你知道,請告訴我。

+2

它將出現在局部變量的範圍。在一個模塊中,你的代碼被封裝在一個函數中。你只是看不到它。 – 2013-03-08 05:20:57

+0

那麼它只是一個匿名函數呢?當然? – Kastor 2013-03-08 05:24:01

+2

是的......我不記得它是否是匿名的,但這並不重要。這是一個功能。爲該函數定義的第一個參數是'exports',並且將一個空對象傳遞給該參數。同一個對象被設置爲函數的this值。你可以用'console.log(arguments [0] === exports,arguments [0] === this);'來測試,並且你將會得到'true'。 – 2013-03-08 05:27:49

回答

10

所以,如果你聲明與var一個變量中的每個節點模塊被包裝成一個函數體爲shown here in the node source code

NativeModule.wrapper = [ 
    '(function (exports, require, module, __filename, __dirname) { ', 
    '\n});' 
]; 

因此,它在功能上本地的模塊,基本上該模塊私有變量。它不是globalmodulemodule.exportsthis的財產。如果您忘記了var,它將作爲屬性進入global對象。如果您明確地在this上創建了一個屬性,則該屬性將進入exports,並可用於其他模塊。

這是一個有希望啓發的小程序。

var aDeclaredVar = '*aDeclaredVar*'; 
undeclaredVar = '*undeclaredVar*'; 
this.aThisProperty = '*aThisProperty*'; 
module.aModuleProperty = '*aModuleProperty*'; 
module.exports.anExportProperty = '*anExportProperty*'; 

console.log('this', this); 
console.log('this === exports', this === exports); 
console.log('this === module', this === module); 
console.log('this === module.exports', this === module.exports); 
console.log('aDeclaredVar', aDeclaredVar); 
console.log('undeclaredVar', undeclaredVar); 
console.log('this.aThisProperty', this.aThisProperty); 
console.log('module.aModuleProperty', module.aModuleProperty); 
console.log('module.exports.anExportProperty', module.exports.anExportProperty); 
console.log('global.undeclaredVar', global.undeclaredVar); 
console.log('global.aDeclaredVar', global.aDeclaredVar); 

而且它的輸出:

this { aThisProperty: '*aThisProperty*', 
    anExportProperty: '*anExportProperty*' } 
this === exports true 
this === module false 
this === module.exports true 
aDeclaredVar *aDeclaredVar* 
undeclaredVar *undeclaredVar* 
this.aThisProperty *aThisProperty* 
module.aModuleProperty *aModuleProperty* 
module.exports.anExportProperty *anExportProperty* 
global.undeclaredVar *undeclaredVar* 
global.aDeclaredVar undefined 
+0

感謝您的源代碼鏈接。 :D我從來沒有試過反思一個函數的本地變量。我不知道是否有黑客做這件事,但肯定我現在看到的行爲很有意義,因爲我知道上下文。這就像書寫小書籤一樣。 – Kastor 2013-03-08 06:08:33

+0

所以我試着運行一個腳本,將結束包裝...};我要去找別的事情去做。 :D – Kastor 2013-03-08 06:27:05

+0

感謝您解決這個問題...正在編寫一個本地節點擴展,並且在這一天掙扎了好幾天! +1 – jkp 2013-05-24 17:54:12