2012-02-12 4 views
1

Я разрабатываю приложение с node.js и socket.io. Я создал небольшой проект с некоторыми переменными и функциями внутри блока, специфичного для подключения. Эти функции имеют доступ к переменным, объявленным в этом блоке, без необходимости передавать значения в частности.NodeJS Функции/Модуль Включить область

Это прекрасно работает и подходит для проекта такого размера. Однако, поскольку я пытался немного очистить код, я изучил факторинг этих функций в их собственный файл и нашел модули, объявленные с использованием export.functionname, как описано здесь: http://nodejs.org/docs/v0.3.2/api/modules.html

Однако эти функции не имеют доступ к переменным в том же блоке, что они обычно делают, когда требуется() 'd in вместо фактического объявления в файле.

Есть ли способ заставить функции во внешнем файле вести себя так, как если бы они были объявлены локально в nodejs?

ответ

2

Существует не без взлома модульной системы, что я и сделал. https://github.com/Benvie/Node.js-Ultra-REPL/blob/master/lib/ScopedModule.js

Не могу сказать, что рекомендую его для производства. В основном проблема связана с самим JavaScript. Узел обертывает модули в функции, поэтому у них есть своя собственная область. Единственный способ поделиться этой областью - это выполнить внутри этой функции, которая бы не работала для модульной (модульной ...) системы. Единственный другой масштаб - глобальный, что также нежелательно.

Уловка, с которой я привык обойти это, заключается в изменении этой функции обертки, чтобы иметь динамические свойства, основанные на внешнем определенном наборе модулей импорта, так что изнутри оболочки модуля все эти параметры выглядят так, как будто они волшебным образом определены, но aren глобальный.

модуль оболочка Node выглядит следующим образом:

(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.

Для этого преобразуйте каждую функцию в строку и оцените ее. Это создаст новую функцию с тем же кодом, но с областью 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, и поэтому они «видят» var1 и var2.