Node.js Modules 模块

模块

https://nodejs.org/docs//v9.2.0/api/modules.html
Node.js has a simple module loading system. In Node.js, files and modules are in one-to-one correspondence (each file is treated as a separate module).
Node.js 有一个简单的模块加载系统,在Node.js,文件和模块是一个一对一的。(每个文件被当做一个独立的模块来处理)

As an example, consider a file named foo.js:
这里有一个例子,一个文件叫做foo.js

const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);

On the first line, foo.js loads the module circle.js that is in the same directory as foo.js.
在第一行,foo.js 加载了circls.js。和foo.js在一个文件夹内。

//定义PI
const { PI } = Math;
//一个箭头函数,求面积
exports.area = (r) => PI * r ** 2;
//箭头函数求面积
exports.circumference = (r) => 2 * PI * r;

The module circle.js has exported the functions area() and circumference(). Functions and objects are added to the root of a module by specifying additional properties on the special exports object.

模块circls.js 有一个导出的函数 area()和circumference(). 函数和对象被加到了一个模块的根部,特别导出了这个对象。
Variables local to the module will be private, because the module is wrapped in a function by Node.js (see module wrapper). In this example, the variable PI is private to circle.js.
模块的本地变量将私有,因为函数内的模块被node.js。在这个例子中,变量PI是circle.js。

The module.exports property can be assigned a new value (such as a function or object).
这个模块导出属性能够被赋予一个新的值(比如一个函数或者对象)

Below, bar.js makes use of the square module, which exports a constructor:
下方,bar.js使用平方根模块,导出一个构造函数。

//定义一个常量

const square = require('./square.js');
//2的平方
const mySquare = square(2);
console.log(`The area of my square is ${mySquare.area()}`);

The square module is defined in square.js:
在square.js中定义了square模块

// assigning to exports will not modify module, use //module.exports
module.exports = (width) => {
  return {
    area: () => width ** 2
  };
};

The module system is implemented in the require(‘module’) module.
在模块系统中执行通过require方式

Accessing the main module

访问主模块
When a file is run directly from Node.js, require.main is set to its module. That means that it is possible to determine whether a file has been run directly by testing require.main === module.
当一个文件直接从Node.js运行时,require.main 是一个他自己模块的集合。这个含义是这个可能是检测require.ain === module 来判断是否直接执行。

For a file foo.js, this will be true if run via node foo.js, but false if run by require(‘./foo’).
对于文件foo.js.这个将返回true,如果运行通过node foo.js 。如果从require(‘./foo’)返回false

Because module provides a filename property (normally equivalent to __filename), the entry point of the current application can be obtained by checking require.main.filename.
因为模块提供了一个文件属性(一般的指向__filename),这个是一个实体指向当前的应用程序,能够绑定为检查 require.main.filename

Addenda: Package Manager Tips

补充,包管理贴士

The semantics of Node.js’s require() function were designed to be general enough to support a number of reasonable directory structures. Package manager programs such as dpkg, rpm, and npm will hopefully find it possible to build native packages from Node.js modules without modification.
Node.js的require函数设计的目的是支持目录结构。包管理程序比如dpkg,rpm和npm将希望能编译原生态包从node.js 模块中不需要修改。

Below we give a suggested directory structure that could work:
下面,我们建议的目录结构

Let’s say that we wanted to have the folder at /usr/lib/node// hold the contents of a specific version of a package.
我们希望文件夹在 /usr/lib/node/包/版本 来保存一些特别的package

Packages can depend on one another. In order to install package foo, it may be necessary to install a specific version of package bar. The bar package may itself have dependencies, and in some cases, these may even collide or form cyclic dependencies.
包能够依赖于别的。为了安装包foo,这个也许需要安装一个特别版本的包组。这个包组也许自己也有一个依赖关系。在很多情况下,这个也许是循环的依赖关系。

Since Node.js looks up the realpath of any modules it loads (that is, resolves symlinks), and then looks for their dependencies in the node_modules folders as described here, this situation is very simple to resolve with the following architecture:
当Node.js查找 realpaht 在任何模块在他加载的时候。看上去独立关系在node_modules文件夹中被描述在之类,这个简单的结构是下面这个

  • /usr/lib/node/foo/1.2.3/ - Contents of the foo package, version 1.2.3.
  • /usr/lib/node/bar/4.3.2/ - Contents of the bar package that foo depends on.
  • /usr/lib/node/foo/1.2.3/node_modules/bar - Symbolic link to - /usr/lib/node/bar/4.3.2/.
  • /usr/lib/node/bar/4.3.2/node_modules/* - Symbolic links to the packages that bar depends on.

Thus, even if a cycle is encountered, or if there are dependency conflicts, every module will be able to get a version of its dependency that it can use.
当这个是一个循环的时候,或者这里有一个依赖冲突,每个模块将被一个依赖关系被使用

When the code in the foo package does require(‘bar’), it will get the version that is symlinked into /usr/lib/node/foo/1.2.3/node_modules/bar. Then, when the code in the bar package calls require(‘quux’), it’ll get the version that is symlinked into /usr/lib/node/bar/4.3.2/node_modules/quux.

当在foo包中的代码 require(‘bar’) 这个将连接到/usr/lib/foo/1.2.3/node_modules/bar.当这个代码在bar package调用require(‘quux’)的时候,这个将临街到/usr/lib/node/bar/4.3.2/node_modules/quux

-笔者注,我看了一下,我的modules在
/Users/sample/.npm-packages/lib/node_modules

Furthermore, to make the module lookup process even more optimal, rather than putting packages directly in /usr/lib/node, we could put them in /usr/lib/node_modules//. Then Node.js will not bother looking for missing dependencies in /usr/node_modules or /node_modules.
而且,为了这个模块检查进程更加高效,比把package放入/usr/lib/node中。我们需要把他们放入/usr/lib/node_modules/name/version。

In order to make modules available to the Node.js REPL, it might be useful to also add the /usr/lib/node_modules folder to the NODEPATHenvironmentvariable.Sincethemodulelookupsusingnodemodulesfoldersareallrelative,andbasedontherealpathofthefilesmakingthecallstorequire(),thepackagesthemselvescanbeanywhere.Node.js/usr/lib/nodemodules NODE_PATH环境变量。让模块查找的时候,使用node_modules文件夹即可。

All Together…

我们来总结一下
To get the exact filename that will be loaded when require() is called, use the require.resolve() function.
为了解析文件名字,我们在require调用的时候,使用require.solve()函数
Putting together all of the above, here is the high-level algorithm in pseudocode of what require.resolve() does:
把所有的东西都放在一起,这里有一个高级别的算法来处理

require(X) from module at path Y
从路径Y require(X)
1. If X is a core module,
   如果X是一个核心模块
   a. return the core module
   b. STOP
2. If X begins with '/'
   如果X开始 /
   a. set Y to be the filesystem root
   然后设置Y作为文件系统的根
3. If X begins with './' or '/' or '../'
   如果X开始是./ / ../
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   作为文件和目录分别加载
4. LOAD_NODE_MODULES(X, dirname(Y))
    加载模块(X,dirname(Y)
    这里注意有一个LOAD_NODE_MODULES函数
5. THROW "not found"
    抛出没有找到
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
    如果X是一个文件,加载X作为Javascript文件
2. If X.js is a file, load X.js as JavaScript text.  STOP
    如果X.js是一个文件,加载X.js
3. If X.json is a file, parse X.json to a JavaScript Object.  STOP
    如果X.json是一个文件,加载X.json
4. If X.node is a file, load X.node as binary addon.  STOP
    如果X.node是一个文件,加载x.node为一个二进制

LOAD_INDEX(X)
如果X是目录开始的套路
分别是index.js
       index.json
       index.node
1. If X/index.js is a file, load X/index.js as JavaScript text.  STOP
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon.  STOP

LOAD_AS_DIRECTORY(X)
加载目录
顺序  package.json
     查找main区域

1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
   d. LOAD_INDEX(M)
2. LOAD_INDEX(X)

LOAD_NODE_MODULES(X, START)
加载
1. let DIRS=NODE_MODULES_PATHS(START)
    把目录制定好
2. for each DIR in DIRS:
   对于目录中的每个目录加载,先文件,然后再目录
   a. LOAD_AS_FILE(DIR/X)
   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
NODE模块路径
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
   a. if PARTS[I] = "node_modules" CONTINUE
   b. DIR = path join(PARTS[0 .. I] + "node_modules")
   c. DIRS = DIRS + DIR
   d. let I = I - 1
5. return DIRS
这个加载不太懂

Caching

缓存
Modules are cached after the first time they are loaded. This means (among other things) that every call to require(‘foo’) will get exactly the same object returned, if it would resolve to the same file.
模块在第一次加载之后可以被缓存。这个意味着每次require(‘foo’)这个能返回相同对象。如果这个被解析为相同的文件

Multiple calls to require(‘foo’) may not cause the module code to be executed multiple times. This is an important feature. With it, “partially done” objects can be returned, thus allowing transitive dependencies to be loaded even when they would cause cycles.
多次调用require(‘foo’)不能导致这个代码被执行多次。这个是一个重要的特型。用这个,部分完成对象能够被返回,这个可以解决循环依赖的问题

To have a module execute code multiple times, export a function, and call that function.
为了模块执行多次,导出一个函数,然后调用函数(不要用require多次啦)

Module Caching Caveats

模块缓存主义事项

Modules are cached based on their resolved filename. Since modules may resolve to a different filename based on the location of the calling module (loading from node_modules folders), it is not a guarantee that require(‘foo’) will always return the exact same object, if it would resolve to different files.
模块被缓存通过他们的文件名。当模块被解析道不同的文件,在不同的位置模块(从node_modules 文件夹),整个不是保障,reuire(‘foo’)将总是返回这个相同的对象,如果这个解析为不同的文件。

Additionally, on case-insensitive file systems or operating systems, different resolved filenames can point to the same file, but the cache will still treat them as different modules and will reload the file multiple times. For example, require(‘./foo’) and require(‘./FOO’) return two different objects, irrespective of whether or not ./foo and ./FOO are the same file.
附加的,在大小写不敏感的文件系统或者操作系统中,不同文件名指向一个相同的文件,按时缓存系统会认为他们是不同的模块,从而加载多次。比如require(‘./foo’)和require(‘./FOO’)将返回2个不同的对象。

Core Modules

核心模块
Node.js has several modules compiled into the binary. These modules are described in greater detail elsewhere in this documentation.
Node.js有很多模块被编译为二进制。这些模块描述在别的文档里面

The core modules are defined within Node.js’s source and are located in the lib/ folder.
核心模块被定义在Node.js中。在lib文件夹内

Core modules are always preferentially loaded if their identifier is passed to require(). For instance, require(‘http’) will always return the built in HTTP module, even if there is a file by that name.
核心模块总是被有限的加载。比如require(‘http’)总是返回内置的HTTP模块。哪怕有一个相同的文件

Cycles

循环

When there are circular require() calls, a module might not have finished executing when it is returned.
当这里有一个循环调用require(),一个模块快也许不能结束执行党这个返回的时候。

Consider this situation:
考虑这个情况
a.js

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');

b.js

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');

main.js

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);

When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
当main.js 加载a.js ,然后a.js 加载b.js。然后b.js 加载a.js。为了能预防无限制循坏,一个未完成复制的a.js 大厨对象到b.js。b.js返回加载,然后导出对象来提供给a.js

By the time main.js has loaded both modules, they’re both finished. The output of this program would thus be:
main.js加载完之后,他们同时结束,然后输出如下

$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done=true, b.done=true

File Modules

文件模块
If the exact filename is not found, then Node.js will attempt to load the required filename with the added extensions: .js, .json, and finally .node.
当一个文件没有找到的时候. Node.js会尝试加载这个文件后缀加上 .js .json .node

.js files are interpreted as JavaScript text files, and .json files are parsed as JSON text files. .node files are interpreted as compiled addon modules loaded with dlopen.
.js文件会被解释为js文件。.json 会被解释为json文件。.node文件会被解析为一个编译好的模块被dlopen加载。

A required module prefixed with ‘/’ is an absolute path to the file. For example, require(‘/home/marco/foo.js’) will load the file at /home/marco/foo.js.
一个被需要的模块前缀是 ‘/’ 绝对路径对这个文件,比如require(‘/home/marco/foo.js’)

A required module prefixed with ‘./’ is relative to the file calling require(). That is, circle.js must be in the same directory as foo.js for require(‘./circle’) to find it.
一个被加载文件如果是前缀是./。那么就是当前文件开始的如何如何(这段比较简单)

Without a leading ‘/’, ‘./’, or ‘../’ to indicate a file, the module must either be a core module or is loaded from a node_modules folder.
如果没有/ ./ ../ 指示,那么模块被认为是核心模块或者这个加载从node_modules文件夹

Folders as Modules

文件夹作为模块

It is convenient to organize programs and libraries into self-contained directories, and then provide a single entry point to that library. There are three ways in which a folder may be passed to require() as an argument.
这个是方便和组织程序和代码到一个包含目录,这个提供单一的实体访问来访问这个库。这个有三种方式来完成

The first is to create a package.json file in the root of the folder, which specifies a main module. An example package.json file might look like this:
第一个是创建一个package.json包在文档的根。这个是一个特殊的模块。下面是一个例子

{ "name" : "some-library",
  "main" : "./lib/some-library.js" }

If this was in a folder at ./some-library, then require(‘./some-library’) would attempt to load ./some-library/lib/some-library.js.
如果这个在一个./some-library的文件夹内。reuqire(‘./some-libaray’)那么会尝试加载./some-libaray/lib/some-library.js

This is the extent of Node.js’s awareness of package.json files.
这个是Node.js的一个扩展package.json(是不是有点类似于python的包文件方式?)

Note: If the file specified by the “main” entry of package.json is missing and can not be resolved, Node.js will report the entire module
as missing with the default error:
注意:如果这个文件中main没有写,那么整个儿不能被解析,那么node.js会报一个错误

Error: Cannot find module 'some-library'

If there is no package.json file present in the directory, then Node.js will attempt to load an index.js or index.node file out of that directory. For example, if there was no package.json file in the above example, then require(‘./some-library’) would attempt to load:
这里如果没有pakcage.json,那么node.js会尝试加载index.js index.node


- ./some-library/index.js
- ./some-library/index.node

Loading from node_modules Folders

从node_modules加载文件

If the module identifier passed to require() is not a core module, and does not begin with ‘/’, ‘../’, or ‘./’, then Node.js starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location. Node will not append node_modules to a path already ending in node_modules.
如果模块的标示被require认为不是一个核心模块。且不是通过 / ./ ../前缀,那么node.js开始查找在当前的模块的父目录。添加/node_modules,尝试加载模块从这个位置。nodes不会添加node_modules到这个路径已经在node_modules

If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.
如果这个没有被发现,这个会被移到父目录。直到操作系统的根目录

For example, if the file at ‘/home/ry/projects/foo.js’ called require(‘bar.js’), then Node.js would look in the following locations, in this order:
比如,文件/home/ry/projects/foo.js调用require(‘bar.js’) node.js将按照下面这个路径来找文件

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

笔者注:看上去就感觉可能存在安全问题,父目录的不停的上翻找呀找

This allows programs to localize their dependencies, so that they do not clash.
这个允许程序来定位他们的依赖包,这样他们不会冲突

It is possible to require specific files or sub modules distributed with a module by including a path suffix after the module name. For instance require(‘example-module/path/to/file’) would resolve path/to/file relative to where example-module is located. The suffixed path follows the same module resolution semantics.
这个是可能的require特别文件或者子目录。比如require(‘example-modul/path/to/file’) 也许会被解析(这种方式好么?)

Loading from the global folders

从全局文件夹加载
If the NODE_PATH environment variable is set to a colon-delimited list of absolute paths, then Node.js will search those paths for modules if they are not found elsewhere.

如果NODE_PATH 环境变量被设置,那么node.js 会搜索搜索这个路径寻找模块,(NODE_PATH类似于PATH的设置,unix是:分开,windowshi;分开)
Note: On Windows, NODE_PATH is delimited by semicolons instead of colons.
注意:在windows NODE_PATH 是;分开

NODE_PATH was originally created to support loading modules from varying paths before the current module resolution algorithm was frozen.
NODE_PATH最初是支持加载模块从很多路径,在当前模块解决算法无效的情况下

NODE_PATH is still supported, but is less necessary now that the Node.js ecosystem has settled on a convention for locating dependent modules. Sometimes deployments that rely on NODE_PATH show surprising behavior when people are unaware that NODE_PATH must be set. Sometimes a module’s dependencies change, causing a different version (or even a different module) to be loaded as the NODE_PATH is searched.
NODE_PATH 始终被支持,这个是不怎么必要的,node.js生态系统会加载依赖模块。有时候分发依赖于NODE_PATH显示一些意想不到的行为。人民没有意识到NODE_PATH必须被设置。有时候一个模块的依赖关系改变了,会导致不同的版本,或者不同的模块,加载当NODE_PATH被使用的时候

Additionally, Node.js will search in the following locations:
Node.js 会搜索如下的位置

  • 1: $HOME/.node_modules
  • 2: $HOME/.node_libraries
  • 3: $PREFIX/lib/node

Where HOMEistheusershomedirectory,and PREFIX is Node.js’s configured node_prefix.
HOMEhome PREFIX 是Node.js 的配置node_prefix
These are mostly for historic reasons.
这里主要是一些历史原因

Note: It is strongly encouraged to place dependencies in the local node_modules folder. These will be loaded faster, and more reliably.
注意:这个强烈鼓励把包放在node_modules文件夹,这样加载会更加迅速。

The module wrapper

模块的封装
Before a module’s code is executed, Node.js will wrap it with a function wrapper that looks like the following:
在这个模块代码被执行前。Node.js会封装一个函数类似于下面这个


(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});


By doing this, Node.js achieves a few things:
Node.js干下面几个事情
- It keeps top-level variables (defined with var, const or let) scoped to the module rather than the global object.
- It helps to provide some global-looking variables that are actually specific to the module, such as:
- The module and exports objects that the implementor can use to export values from the module.
- The convenience variables __filename and __dirname, containing the module’s absolute filename and directory path.

这个保证最高级别的变量(用var const let)作用范围模块高于全局对象(函数中的变量的作用域高于全局变量作用域)
这个帮助提供一些全局变量,这个能操作这个模块比如
这个模块和导出对象执行能够export值从这个模块中
这个方便变量 __filename 和__dirnames 包含模块的绝对名字和路径

The module scope

模块的作用域

__dirname

The directory name of the current module. This the same as the path.dirname() of the __filename.
当前模块的目录名字,这个相同于 __filename的path.dirname()
path.dirname(__filename);

Example: running node example.js from /Users/mjr
比如运行example.js 从/Users/mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr

__filename

The file name of the current module. This is the resolved absolute path of the current module file.

For a main program this is not necessarily the same as the file name used in the command line.

See __dirname for the directory name of the current module.

Examples:

Running node example.js from /Users/mjr

console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr

这段看一下例子,还是简单的,一个是__filename, 一个是__dirname

exports

A reference to the module.exports that is shorter to type. See the section about the exports shortcut for details on when to use exports and when to use module.exports.
对于 module.exports的引用,具体看一下export的介绍

module

A reference to the current module, see the section about the module object. In particular, module.exports is used for defining what a module exports and makes available through require().
反正就是一个模块

require()

To require modules.

require.cache

Modules are cached in this object when they are required. By deleting a key value from this object, the next require will reload the module. Note that this does not apply to native addons, for which reloading will result in an Error.
模块被缓存当这个被require的时候,被删除的时候会。。。。下次被需require。注意这个不被apple到一个原生态的addons上,这个会发返回一个错误。

require.extensions

Instruct require on how to handle certain file extensions.
Process files with the extension .sjs as .js:

require.extensions['.sjs'] = require.extensions['.js'];

这个高速node.js哪些扩展名是ok的
默认是.js,你可以把sjs添加进去

Deprecated In the past, this list has been used to load non-JavaScript modules into Node.js by compiling them on-demand. However, in practice, there are much better ways to do this, such as loading modules via some other Node.js program, or compiling them to JavaScript ahead of time.

Since the module system is locked, this feature will probably never go away. However, it may have subtle bugs and complexities that are best left untouched.
当module系统被锁,这个特征也许不会再继续,但这个也许微妙的bug,最好不要用这个特性

Note that the number of file system operations that the module system has to perform in order to resolve a require(…) statement to a filename scales linearly with the number of registered extensions.
注意,这个文件系统的操作模块系统,执行一个为了解决require的恶性的扩展用一个注册了的扩展名

In other words, adding extensions slows down the module loader and should be discouraged.
或者说,添加扩展降低模块的加载是不被鼓励的

require.resolve(request[, options])

request The module path to resolve.
options
paths Paths to resolve module location from. If present, these paths are used instead of the default resolution paths. Note that each of these paths is used as a starting point for the module resolution algorithm, meaning that the node_modules hierarchy is checked from this location.
路径 路径类定位模块的位置,这个路径被使用在默认的解析路径。注意每个路径被使用指向解析算法,意味着node_modules 继承被勾选了
Returns:
Use the internal require() machinery to look up the location of a module, but rather than loading the module, just return the resolved filename.
使用内置的require来查找模块的位置,但和加载模块相比,着只是解析名字

require.resolve.paths(request)

Returns an array containing the paths searched during resolution of request.
返回一个数组,包含路径

The module Object

In each module, the module free variable is a reference to the object representing the current module. For convenience, module.exports is also accessible via the exports module-global. module is not actually a global but rather local to each module.
在每个模块中,模块自由的变量指向对象在当前模块中,为了方便,module.exports 是一个访问通过导出模块-全局。模块不是一个全局,只是本地使用。

module.children

The module objects required by this one.
这个模块需要自己

module.exports

The module.exports object is created by the Module system. Sometimes this is not acceptable; many want their module to be an instance of some class. To do this, assign the desired export object to module.exports. Note that assigning the desired object to exports will simply rebind the local exports variable, which is probably not what is desired.
modules.exports 对象是一个创建被模块系统。有时候这个是不被接受的,很多希望他们模块是一些class的实例。为了达到这个目的,设计一个渴望的对象来导出简单的绑定到本地导出变量,这个是也许被期望的。

For example suppose we were making a module called a.js

const EventEmitter = require('events');

module.exports = new EventEmitter();

// Do some work, and after some time emit
// the 'ready' event from the module itself.
// 在时间到期之后做一些事情
setTimeout(() => {
  module.exports.emit('ready');
}, 1000);

Then in another file we could do
然后我们在别的文件可以干如下的事情

const a = require('./a');
a.on('ready', () => {
  console.log('module a is ready');
});

Note that assignment to module.exports must be done immediately. It cannot be done in any callbacks. This does not work:
注意module.exports 被立刻执行,这个不能被任何调用结束,下面不能运行

x.js

setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0);

y.js

const x = require('./x');
console.log(x.a);

exprots shortcut

The exports variable is available within a module’s file-level scope, and is assigned the value of module.exports before the module is evaluated.
It allows a shortcut, so that module.exports.f = … can be written more succinctly as exports.f = …. However, be aware that like any variable, if a new value is assigned to exports, it is no longer bound to module.exports:
export 变量是可以的,在模块文件级的作用域内。并且这个是被关联到module.exports的变量。这个允许做一个快捷键,module.exports.f= 能给被谢伟 exports.f 然而这个要注意这个类似于任何变量,如果一个新的指指向export,那么这个不能用module.exports.

module.exports.hello = true; // Exported from require of module
exports = { hello: false };  // Not exported, only available in the module
//exports 变成了一个变量

To illustrate the behavior, imagine this hypothetical implementation of require(), which is quite similar to what is actually done by require():
为了这个目的,我们执行了require,但是没有任何软用

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // Module code here. In this example, define a function.
    function someFunc() {}
    exports = someFunc;
    // At this point, exports is no longer a shortcut to module.exports, and
    // this module will still export an empty default object.
    module.exports = someFunc;
    // At this point, the module will now export someFunc, instead of the
    // default object.
  })(module, module.exports);
  return module.exports;
}

module.filename

The fully resolved filename to the module.

module.id

The identifier for the module. Typically this is the fully resolved filename.

module.loaded

Whether or not the module is done loading, or is in the process of loading.

module.parent

Module object
The module that first required this one.
模块的爸爸

module.require(id)

The module.require method provides a way to load a module as if require() was called from the original module.
这个方法可以提供一个方法来加载模块

Note: In order to do this, it is necessary to get a reference to the module object. Since require() returns the module.exports, and the module is typically only available within a specific module’s code, it must be explicitly exported in order to be used.
注意:为了做这个,必须指向一个模块对象,当require返回module.exports,这个模块是典型的只有变量和特定的模块代码,这个必须导出来使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值