2012-02-12 50 views
1

我正在開發一個帶有node.js和socket.io的應用程序。我已經在特定於連接的塊中構建了一個包含一些變量和函數的小型項目。這些函數可以訪問在該塊中聲明的變量,而不需要特別傳遞值。NodeJS函數/模塊包含範圍

這工作得很好,是這個規模的項目可以接受的。但是,當我試圖清理代碼時,我考慮將這些函數分解到它們自己的文件中,並找到使用exports.functionname聲明的模塊,如下所述:http://nodejs.org/docs/v0.3.2/api/modules.html

但是,這些函數沒有訪問同一塊中的變量,正如它們在require()'d in時通常所做的那樣,而不是在文件中實際聲明。

有一些方法,使功能在外部文件的行爲,就好像他們在本地的NodeJS聲明?

回答

2

沒有沒有黑客的模塊系統,而這正是我所做的。 https://github.com/Benvie/Node.js-Ultra-REPL/blob/master/lib/ScopedModule.js

我不能說我推薦它的生產。基本上這個問題更多的是JavaScript本身。節點將模塊包裝在一個函數中,以便它們擁有自己的專用範圍。在該範圍內共享的唯一方法是在該功能內部執行,這對於模塊(模塊化...)系統來說不會起作用。唯一的其他範圍是全球性的,這也是不可取的。

我用來解決這個問題的訣竅是改變這個包裝函數,使其具有基於外部定義的模塊導入集的動態屬性,以便從模塊包裝器內部看到所有這些參數看起來像是神奇地定義的,但aren全球化。

節點的模塊包裹器看起來是這樣的:

(function (exports, module, require, __filename, __dirname){ 
    /**module**/ 
}) 

凡礦只是增加了更多的參數,並確保他們在執行模塊包裹器之前要解決。

我有它加載一個模塊之前閱讀給定文件夾命名爲「.deps.json」文件。 一個例子一個會是這樣

[{ 
    "providers": [ "./utility/", 
        "./settings/" ], 
    "receivers": [ "*" ] 
}] 

所以它會加載在這些子文件夾的模塊,然後暴露每一個如在包裝的參數,基於所述文件名命名。

1

常用的清潔方法是將你的模塊,這需要必要的變量作爲參數來定義一個函數:

// extracted_file.js 
exports.handler = function(param1, param2) { 
    return param1 + param2; 
} 

// caller file 
var extractedHandler = require('./extracted_file').handle; 

var localVar1 = 1300, 
    localVar2 = 37; 
console.log(extractedHandler(localVar1, localVar2)); 
0

您可以更改使用toString()和可怕的eval功能範圍。

如果你的職能是在說lib.js如下: -

var lib = {} 
lib.foo = function() { console.log(var1) } 
lib.bar = function() { console.log(var2) } 
module.exports = lib 

在main.js你可以有這樣的: -

var var1 = 1 
var var2 = 2 
var ob1 = require('./lib') 
ob1.foo() 
ob1.bar() 

當你運行它的ob1.foo( )行給出一個ReferenceError,var1沒有定義。這是因爲foo()的作用域來自lib.js而不是你的主要js文件,而var1對它來說是不可見的。 ob1.foo是對具有lib.js作用域的函數的引用。您需要使用main.js作用域創建新的引用。

爲此相互轉換功能串和eval它。這將創建一個具有相同代碼但具有main.js範圍的新函數。這裏有一種使用setMainScope方法的方法,該方法遍歷所有將其作用域更改爲main.js的函數。

var var1 = 1 
var var2 = 2 
var ob1 = {} 

ob1.setMainScope = function(ob2) { 
for(var prop in ob2) { 
    if(!ob2.hasOwnProperty(prop)) {continue} 
    if(typeof ob2[prop] !== 'function') {continue} 
    this[prop] = eval("(" + ob2[prop].toString() + ")") 
} 
} 

ob1.setMainScope(require('./lib')) 
ob1.foo() // 1 
ob1.bar() // 2 

現在所有的作品很好,但用eval。的foo()bar()範圍現在是main.js,所以他們「看到」 var1var2