提问人:TIMEX 提问时间:4/27/2011 最后编辑:TIMEX 更新时间:10/24/2023 访问量:1116329
在Node.js中,如何“包含”其他文件中的函数?
In Node.js, how do I "include" functions from my other files?
问:
假设我有一个名为 app.js 的文件。很简单:
var express = require('express');
var app = express.createServer();
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.get('/', function(req, res){
res.render('index', {locals: {
title: 'NowJS + Express Example'
}});
});
app.listen(8080);
如果我在“tools.js”中有一个函数怎么办。如何导入它们以在apps.js中使用?
或。。。我是否应该将“工具”变成一个模块,然后需要它?<<看起来很难,我宁愿做tools.js文件的基本导入。
答:
你可以把你的函数放在全局变量中,但最好把你的工具脚本变成一个模块。这真的不是太难 - 只需将公共 API 附加到对象即可。有关更多详细信息,请查看了解Node.js的导出模块。exports
评论
你可以要求任何js文件,你只需要声明你想要公开的内容。
// tools.js
// ========
module.exports = {
foo: function () {
// whatever
},
bar: function () {
// whatever
}
};
var zemba = function () {
}
在应用文件中:
// app.js
// ======
var tools = require('./tools');
console.log(typeof tools.foo); // => 'function'
console.log(typeof tools.bar); // => 'function'
console.log(typeof tools.zemba); // => undefined
评论
require("http://javascript-modules.googlecode.com/svn/functionChecker.js")
如果尽管有所有其他答案,您仍然希望在传统上将文件包含在node.js源文件中,则可以使用以下命令:
var fs = require('fs');
// file is included here:
eval(fs.readFileSync('tools.js')+'');
- 空字符串串联对于将文件内容获取为字符串而不是对象是必要的(如果您愿意,也可以使用)。
+''
.toString()
- eval() 不能在函数内部使用,必须在全局范围内调用,否则将无法访问任何函数或变量(即您无法创建实用函数或类似的东西)。
include()
请注意,在大多数情况下,这是不好的做法,您应该编写一个模块。但是,在极少数情况下,本地上下文/命名空间的污染是您真正想要的。
更新 2015-08-06
另请注意,这不适用于(当您处于“严格模式”时),因为执行导入的代码无法访问“导入”文件中定义的函数和变量。严格模式强制执行由较新版本的语言标准定义的一些规则。这可能是避免此处描述的解决方案的另一个原因。"use strict";
评论
Udo G. 说:
- eval() 不能在函数内部使用,必须在函数内部调用 全局作用域,否则将没有函数或变量 可访问的(即您不能创建include()实用程序函数或 类似的东西)。
他是对的,但有一种方法可以从函数中影响全局范围。改进他的榜样:
function include(file_) {
with (global) {
eval(fs.readFileSync(file_) + '');
};
};
include('somefile_with_some_declarations.js');
// the declarations are now accessible here.
希望,这会有所帮助。
Node.js中的 vm 模块提供了在当前上下文(包括全局对象)中执行 JavaScript 代码的功能。查看 http://nodejs.org/docs/latest/api/vm.html#vm_vm_runinthiscontext_code_filename
请注意,截至今天,vm 模块中存在一个 bug,该 bug 在从新上下文调用时会阻止 runInThisContext 执行正确的操作。仅当主程序在新上下文中执行代码,然后该代码调用 runInThisContext 时,这才有意义。查看 https://github.com/joyent/node/issues/898
可悲的是,Fernando 建议的 with(global) 方法不适用于像“function foo() {}”这样的命名函数
简而言之,这里有一个适合我的include()函数:
function include(path) {
var code = fs.readFileSync(path, 'utf-8');
vm.runInThisContext(code, path);
}
评论
这是我迄今为止创造的最好的方式。
var fs = require('fs'),
includedFiles_ = {};
global.include = function (fileName) {
var sys = require('sys');
sys.puts('Loading file: ' + fileName);
var ev = require(fileName);
for (var prop in ev) {
global[prop] = ev[prop];
}
includedFiles_[fileName] = true;
};
global.includeOnce = function (fileName) {
if (!includedFiles_[fileName]) {
include(fileName);
}
};
global.includeFolderOnce = function (folder) {
var file, fileName,
sys = require('sys'),
files = fs.readdirSync(folder);
var getFileName = function(str) {
var splited = str.split('.');
splited.pop();
return splited.join('.');
},
getExtension = function(str) {
var splited = str.split('.');
return splited[splited.length - 1];
};
for (var i = 0; i < files.length; i++) {
file = files[i];
if (getExtension(file) === 'js') {
fileName = getFileName(file);
try {
includeOnce(folder + '/' + file);
} catch (err) {
// if (ext.vars) {
// console.log(ext.vars.dump(err));
// } else {
sys.puts(err);
// }
}
}
}
};
includeFolderOnce('./extensions');
includeOnce('./bin/Lara.js');
var lara = new Lara();
您仍然需要告知要导出的内容
includeOnce('./bin/WebServer.js');
function Lara() {
this.webServer = new WebServer();
this.webServer.start();
}
Lara.prototype.webServer = null;
module.exports.Lara = Lara;
我也在寻找 NodeJS 的“include”函数,并检查了 Udo G 提出的解决方案 - 请参阅消息 https://stackoverflow.com/a/8744519/2979590。他的代码不适用于我包含的 JS 文件。 最后,我解决了这样的问题:
var fs = require("fs");
function read(f) {
return fs.readFileSync(f).toString();
}
function include(f) {
eval.apply(global, [read(f)]);
}
include('somefile_with_some_declarations.js');
当然,这很有帮助。
评论
这是一个简单明了的解释:
Server.js内容:
// Include the public functions from 'helpers.js'
var helpers = require('./helpers');
// Let's assume this is the data which comes from the database or somewhere else
var databaseName = 'Walter';
var databaseSurname = 'Heisenberg';
// Use the function from 'helpers.js' in the main file, which is server.js
var fullname = helpers.concatenateNames(databaseName, databaseSurname);
Helpers.js内容:
// 'module.exports' is a node.JS specific feature, it does not work with regular JavaScript
module.exports =
{
// This is the function which will be called in the main file, which is server.js
// The parameters 'name' and 'surname' will be provided inside the function
// when the function is called in the main file.
// Example: concatenameNames('John,'Doe');
concatenateNames: function (name, surname)
{
var wholeName = name + " " + surname;
return wholeName;
},
sampleFunctionTwo: function ()
{
}
};
// Private variables and functions which will not be accessible outside this file
var privateFunction = function ()
{
};
您不需要新功能或新模块。 如果您不想使用命名空间,则只需执行正在调用的模块。
在tools.js
module.exports = function() {
this.sum = function(a,b) { return a+b };
this.multiply = function(a,b) { return a*b };
//etc
}
在app.js
或任何其他.js,如myController.js:
而不是
var tools = require('tools.js')
这迫使我们使用命名空间并调用类似tools.sum(1,2);
我们可以简单地调用
require('tools.js')();
然后
sum(1,2);
就我而言,我有一个带有控制器的文件ctrls.js
module.exports = function() {
this.Categories = require('categories.js');
}
之后,我可以在每种情况下用作公共类Categories
require('ctrls.js')()
评论
this
require('blah.js')();
包含文件并在给定的(非全局)上下文中运行它
fileToInclude.js
define({
"data": "XYZ"
});
main.js
var fs = require("fs");
var vm = require("vm");
function include(path, context) {
var code = fs.readFileSync(path, 'utf-8');
vm.runInContext(code, vm.createContext(context));
}
// Include file
var customContext = {
"define": function (data) {
console.log(data);
}
};
include('./fileToInclude.js', customContext);
假设我们想调用函数 ping() 和 add(30,20),它位于lib.js文件中 与main.js相比
main.js
lib = require("./lib.js")
output = lib.ping();
console.log(output);
//Passing Parameters
console.log("Sum of A and B = " + lib.add(20,30))
lib.js
this.ping=function ()
{
return "Ping Success"
}
//Functions with parameters
this.add=function(a,b)
{
return a+b
}
评论
我也在寻找一个选项来包含不编写模块的代码,例如使用来自不同项目的相同经过测试的独立源代码进行Node.js服务 - jmpautette的答案为我做到了。
好处是,你不会污染命名空间,我没有问题,而且效果很好。"use strict";
下面是一个完整的示例:
要加载的脚本 - /lib/foo.js
"use strict";
(function(){
var Foo = function(e){
this.foo = e;
}
Foo.prototype.x = 1;
return Foo;
}())
SampleModule - index.js
"use strict";
const fs = require('fs');
const path = require('path');
var SampleModule = module.exports = {
instAFoo: function(){
var Foo = eval.apply(
this, [fs.readFileSync(path.join(__dirname, '/lib/foo.js')).toString()]
);
var instance = new Foo('bar');
console.log(instance.foo); // 'bar'
console.log(instance.x); // '1'
}
}
希望这在某种程度上有所帮助。
它像下面这样与我一起工作......
Lib1.js
//Any other private code here
// Code you want to export
exports.function1 = function(params) {.......};
exports.function2 = function(params) {.......};
// Again any private code
现在,在 Main.js 文件中,您需要包含Lib1.js
var mylib = requires('lib1.js');
mylib.function1(params);
mylib.function2(params);
请记得将Lib1.js放在node_modules文件夹中。
就像你有一个文件等等?abc.txt
创建 2 个文件: 和 ,然后编写以下代码:fileread.js
fetchingfile.js
fileread.js
function fileread(filename) {
var contents= fs.readFileSync(filename);
return contents;
}
var fs = require("fs"); // file system
//var data = fileread("abc.txt");
module.exports.fileread = fileread;
//data.say();
//console.log(data.toString());
}
在编写此代码时:fetchingfile.js
function myerror(){
console.log("Hey need some help");
console.log("type file=abc.txt");
}
var ags = require("minimist")(process.argv.slice(2), { string: "file" });
if(ags.help || !ags.file) {
myerror();
process.exit(1);
}
var hello = require("./fileread.js");
var data = hello.fileread(ags.file); // importing module here
console.log(data.toString());
现在,在终端中: $ 节点fetchingfile.js --file=abc.txt
您将文件名作为参数传递,此外,还包括所有文件而不是传递它。readfile.js
谢谢
使用 node.js 和 express.js 框架时的另一种方法
var f1 = function(){
console.log("f1");
}
var f2 = function(){
console.log("f2");
}
module.exports = {
f1 : f1,
f2 : f2
}
将其存储在名为 S 的 JS 文件和 Statics 文件夹中
现在使用函数
var s = require('../statics/s');
s.f1();
s.f2();
在我看来,另一种方法是在调用 require() 函数时执行 lib 文件中的所有内容 (function(/* things here */){})();这样做将使所有这些函数成为全局范围,就像 eval() 解决方案一样
来源/lib.js
(function () {
funcOne = function() {
console.log('mlt funcOne here');
}
funcThree = function(firstName) {
console.log(firstName, 'calls funcThree here');
}
name = "Mulatinho";
myobject = {
title: 'Node.JS is cool',
funcFour: function() {
return console.log('internal funcFour() called here');
}
}
})();
然后在主代码中,您可以按名称调用函数,如下所示:
main.js
require('./src/lib')
funcOne();
funcThree('Alex');
console.log(name);
console.log(myobject);
console.log(myobject.funcFour());
将进行此输出
bash-3.2$ node -v
v7.2.1
bash-3.2$ node main.js
mlt funcOne here
Alex calls funcThree here
Mulatinho
{ title: 'Node.JS is cool', funcFour: [Function: funcFour] }
internal funcFour() called here
undefined
当你调用我的 object.funcFour() 时要注意 undefined,如果你用 eval() 加载,它会是一样的。希望对:)有所帮助
你可以简单地.require('./filename')
例如。
// file: index.js
var express = require('express');
var app = express();
var child = require('./child');
app.use('/child', child);
app.get('/', function (req, res) {
res.send('parent');
});
app.listen(process.env.PORT, function () {
console.log('Example app listening on port '+process.env.PORT+'!');
});
// file: child.js
var express = require('express'),
child = express.Router();
console.log('child');
child.get('/child', function(req, res){
res.send('Child2');
});
child.get('/', function(req, res){
res.send('Child');
});
module.exports = child;
请注意:
- 你不能在子文件上监听 PORT,只有父 express 模块有 PORT 监听器
- 子项使用的是“路由器”,而不是父级 Express moudle。
创建两个 js 文件
// File cal.js
module.exports = {
sum: function(a,b) {
return a+b
},
multiply: function(a,b) {
return a*b
}
};
主 js 文件
// File app.js
var tools = require("./cal.js");
var value = tools.sum(10,20);
console.log("Value: "+value);
控制台输出
Value: 30
评论
我只想补充一点,如果您只需要从tools.js导入的某些函数,那么您可以使用自 6.4 版以来node.js支持的解构赋值 - 请参阅 node.green。
示例:(两个文件位于同一文件夹中)
tools.js
module.exports = {
sum: function(a,b) {
return a + b;
},
isEven: function(a) {
return a % 2 == 0;
}
};
main.js
const { isEven } = require('./tools.js');
console.log(isEven(10));
输出: true
这还可以避免将这些函数赋值为另一个对象的属性,就像以下(常见)赋值中的情况一样:
const tools = require('./tools.js');
您需要调用的地方。tools.isEven(10)
注意:
不要忘记用正确的路径作为文件名的前缀 - 即使两个文件位于同一文件夹中,您也需要以./
来自Node.js文档:
不带前导 '/'、'./' 或 '../' 表示文件,模块 必须是核心模块或从 node_modules 文件夹加载。
app.js
let { func_name } = require('path_to_tools.js');
func_name(); //function calling
tools.js
let func_name = function() {
...
//function body
...
};
module.exports = { func_name };
用:
var mymodule = require("./tools.js")
app.js:
module.exports.<your function> = function () {
<what should the function do>
}
评论
./tools.js
创建两个文件,例如和app.js
tools.js
app.js
const tools= require("./tools.js")
var x = tools.add(4,2) ;
var y = tools.subtract(4,2);
console.log(x);
console.log(y);
tools.js
const add = function(x, y){
return x+y;
}
const subtract = function(x, y){
return x-y;
}
module.exports ={
add,subtract
}
输出
6
2
要把“工具”变成一个模块,我一点也不难看。尽管有所有其他答案,我仍然建议使用 module.exports:
//util.js
module.exports = {
myFunction: function () {
// your logic in here
let message = "I am message from myFunction";
return message;
}
}
现在我们需要将此导出分配给全局范围(在您的 app|index|server.js 中)
var util = require('./util');
现在,您可以将函数引用和调用为:
//util.myFunction();
console.log(util.myFunction()); // prints in console :I am message from myFunction
创建两个 JavaScript 文件。例如 和import_functions.js
main.js
1.) import_functions.js
// Declaration --------------------------------------
module.exports =
{
add,
subtract
// ...
}
// Implementation ----------------------------------
function add(x, y)
{
return x + y;
}
function subtract(x, y)
{
return x - y;
}
// ...
2.) main.js
// include ---------------------------------------
const sf= require("./import_functions.js")
// use -------------------------------------------
var x = sf.add(4,2);
console.log(x);
var y = sf.subtract(4,2);
console.log(y);
输出
6
2
评论
要在 Unix 环境中以交互方式测试模块,可以使用如下所示:./test.js
>> node -e "eval(''+require('fs').readFileSync('./test.js'))" -i
...
Node 基于 commonjs 模块和最近的 esm 模块工作。基本上,您应该在单独的.js文件中创建模块并使用导入/导出(module.exports 和 require)。
浏览器上的 Javascript 的工作方式因范围而异。有全局作用域,通过 clojures(其他函数中的函数),你有私有作用域。
因此,在 node 中,导出您将在其他模块中使用的函数和对象。
IMO最干净的方式如下,在tools.js:
function A(){
.
.
.
}
function B(){
.
.
.
}
module.exports = {
A,
B
}
然后,在app.js中,只需要如下tools.js:const tools = require("tools");
使用 ESM 模块系统:
a.js
:
export default function foo() {};
export function bar() {};
b.js
:
import foo, {bar} from './a.js';
我想使用一个静态函数和一个来自 JS 类的方法。 否则我使用 Typescript,但这里它只是编译后的后脚本。 到目前为止,以最疯狂的方式处理了它,并混合了上述所有答案:
js/tools.js:
class Tools {
count = 0;
constructor(count) {
this.count = count;
}
static add = function (x, y) { // static function
return x + y;
}
incrementCountByValue(value) // instance method
{
this.count += value;
}
}
}
module.exports = {
Tools
}
app.js:
const Tools = require("./js/tools").Tools;
console.log(Tools.add(2,2));// console output: 4
const tools = new Tools(5);
console.log(tools.count);// console output: 5
tools.incrementCountByValue(3);
console.log(tools.count); // console output: 8
评论
require
./mydir
mydir
node_modules