Javascript 将节点模块变量注入作用域

Javascript 将节点模块变量注入作用域,javascript,node.js,scope,node-modules,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 = &qu

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

module.js:

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

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

    var variable = "test";
};
module.exports = function () {
    eval(String(inject));

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

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

test.fn();
test.fn2();
otherFunction(variable);
require("./module.js")();

$module1.fn();
我不想做这样的事情,
$=require(“./module.js”)();$。test.fn()
我想在不使用包装器变量的情况下将此变量注入app.js范围

编辑: 我最后用了这个:

module.js:

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

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

    var variable = "test";
};
module.exports = function () {
    eval(String(inject));

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

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

test.fn();
test.fn2();
otherFunction(variable);
require("./module.js")();

$module1.fn();

模块中的顶级作用域实际上是一个函数作用域(node.js加载程序将每个模块包装在一个函数中,然后调用该函数来执行模块中的代码)。因此,没有公共可用的“根”对象,我们可以通过编程将属性分配给它

因此,这意味着在一个模块中,如果不使用
eval()
,就不可能在模块作用域的顶层以编程方式添加新变量。函数作用域在Javascript中就是不能这样工作

您还可以让模块将内容分配给
global
对象,在该对象中可以不带前缀地使用这些内容,但无论如何,这都不是推荐的做法。node.js模块的全部要点是避免使用任何全局变量,并使代码完全自包含,几乎不会发生全局冲突

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

最好的方法是以“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"
    }
};

这个答案不应该鼓励您在node.js模块中使用
global
(参见上面的jfriend00评论),因为它会使您的代码容易与其他模块发生名称冲突,从而降低模块的可移植性。

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

module.js:

global.test = {
    fn: function() {
        //Do something
    },
    fn2: function() {
        //Do something different
    },
    variable: "test variable"
}
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);
require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);

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

您可以使用IIFE执行类似操作。当需要时,该方法将自动运行并返回一个对象,然后您可以在应用程序中使用该对象

module.js:

global.test = {
    fn: function() {
        //Do something
    },
    fn2: function() {
        //Do something different
    },
    variable: "test variable"
}
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);
require("./module.js"); //just include, no need for a wrapper variable
test.fn();
test.fn2();
console.log(test.variable);

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

正如我所说,这正是我不想实现的。有没有其他方法可以将变量注入作用域?@ddl-我回答了你的问题,你不能这样做,除非你想以一种相当粗俗的方式对字符串使用
eval()
。在我的回答中,我进一步解释了为什么不能使用普通Javascript执行此操作。@ddl-如果您想使用
eval()
执行此操作,请让您的模块导出一个巨大的Javascript字符串,并让您的app.js从模块中获取该字符串,然后
eval()
将其导入app.js。我不建议你那样做。node.js中的模块体系结构导致
moduleName.method()
成为最常见的设计模式,大多数node.js开发人员已经习惯了这一点。如果你真的想要一个快捷方式,你可以将模块变量分配给你自己的局部变量,但是你不能用
eval()
@ddl自动完成这项工作-这感觉就像你只是试图避免在模块中键入
moduleName.method()
。这就是“node.js方式”,这种方式有很多正当的理由。如果您想编写健壮的、可重用的node.js代码并与他人共享,我建议您学习并使用常见的node.js设计模式,即使它们一开始感觉有点不同或尴尬。它的工作方式背后有逻辑。我知道我想做一件疯狂的事情,但我已经找到了一种方法,感谢反馈
module.exports=function(){eval(String((this.$fn=function(){console.log($test.fn());}
皱眉。在node.js中使用globals,只是为了节省一点输入不是推荐的做法。同意这一点,我只是想展示这种可能性,因为@ddl明确要求在全局范围内提供模块对象。实际上,OP要求的是“app.js范围”,而不是全局范围。它们不一样。