将节点模块变量注入范围

时间:2015-09-28 20:24:38

标签: javascript node.js scope node-modules

是否可以使用节点模块实现此行为?

module.js:

module.exports = function () {
    var test.fn = function () {
        console.log("$test.fn()");
    }

    var test.fn2 = function () {
        console.log("$test.fn2()");
    }

    var variable = "test";
};

app.js:

require("./module.js")();

test.fn();
test.fn2();
otherFunction(variable);

我不想做这样的事情$ = require("./module.js")(); $.test.fn(); 我想将这些变量注入到没有包装变量的app.js范围内。

编辑:

我最终使用了这个:

module.js:

module.exports = function () {
    eval(String(inject));

    var inject = (
        this.$module1 = {},
        this.$module1.fn = function () {
            console.log("$module1.fn()");
        }
        );
};

app.js:

require("./module.js")();

$module1.fn();

3 个答案:

答案 0 :(得分:3)

模块中的顶级作用域实际上是一个函数作用域(node.js加载器将每个模块包装在一个函数中,然后调用该函数来执行模块中的代码)。因此,没有公开的" root"我们可以通过编程方式为其分配属性的对象。

因此,这意味着在模块中无法以编程方式在模块范围的顶层添加新变量而不在相当大的黑客中使用eval()。功能范围在Javascript中不会那样工作。

您也可以让模块将事物分配给global对象,在没有前缀的情况下可以使用它们,但这不是任何推荐的做法。 node.js模块的重点是避免使用任何全局变量并使代码完全自包含,几乎没有全局冲突的可能性。

或者,您可以让您的模块导出一个巨大的Javascript字符串,然后在app.js中导出eval(),以便在模块范围内定义新变量。再次 - 不推荐。

你最好的事情是做" node.js方式"并将所有内容放在一个对象上并导出该对象。这是一个变体:

app.js

var test = require("./module.js")();

test.fn();                  // "executing fn"
test.fn2();                 // "executing fn2"
console.log(test.myVar);    // "test"

module.js

module.exports = function () {
    return {
       fn: function () {
           console.log("executing fn");
       },
       fn2: function() {
            console.loog("executing fn2");
       },
       myVar: "test"
    }
};

答案 1 :(得分:0)

这个答案不应该鼓励你在node.js模块中使用global(请参阅上面的jfriend00及其评论),因为它会使你的代码容易受到与其他模块名称冲突的攻击,因此你的模块不太便携。

在module.js中,您可以访问node.js运行时环境的global对象。

<强> module.js:

global.test = {
    fn: function() {
        //Do something
    },
    fn2: function() {
        //Do something different
    },
    variable: "test variable"
}

<强> app.js

require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);

请注意,如果全局变量test已存在,则此技术将覆盖它。

答案 2 :(得分:0)

你可以使用IIFE做类似的事情。该方法在需要时将自动运行并返回一个对象,然后您可以在应用程序中使用该对象。

<强> module.js:

global.test = (function() {
  return {
    fn: function() {
      console.log("executing fn");
    },
    fn2: function() {
      console.log("executing fn2");
    },
    variable: "test"
  }
})();

<强> app.js

require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);

请注意,如果全局变量test已存在,则此技术将覆盖它。