Heim  >  Artikel  >  Web-Frontend  >  Ausführliche Erklärung von commonJS

Ausführliche Erklärung von commonJS

php中世界最好的语言
php中世界最好的语言Original
2018-03-09 14:08:0111559Durchsuche

Dieses Mal erkläre ich Ihnen ausführlich, welche Vorsichtsmaßnahmen bei der Verwendung von commonJS gelten.

CommonJS-Übersicht

Der gesamte Code wird im Modulbereich ausgeführt und verschmutzt nicht den globalen Bereich.
Das Modul kann mehrmals geladen werden, aber es wird nur einmal ausgeführt, wenn es zum ersten Mal geladen wird, und dann werden die laufenden Ergebnisse zwischengespeichert. Beim späteren Laden werden die zwischengespeicherten Ergebnisse direkt gelesen. Damit das Modul wieder funktioniert, muss der Cache geleert werden.
Module werden in der Reihenfolge geladen, in der sie im Code erscheinen.

2. Modulobjekt

In jedem Modul gibt es ein Modulobjekt, das das aktuelle Modul darstellt. Es hat die folgenden Eigenschaften.

console.log(module.id) //模块的识别符,通常是带有绝对路径的模块文件名。console.log(module.filename) //模块的文件名,带有绝对路径。console.log(module.loaded) //返回一个布尔值,表示模块是否已经完成加载。console.log(module.parent) //返回一个对象,表示调用该模块的模块。console.log(module.children) //返回一个数组,表示该模块要用到的其他模块。console.log(module.exports) //表示模块对外输出的值。

2.1 module.exports-Attribut

Das module.exports-Attribut stellt die externe Ausgabeschnittstelle des aktuellen Moduls dar. Wenn andere Dateien das Modul laden, lesen sie tatsächlich die Variable module.exports .

2.2 Exportvariable

Der Einfachheit halber stellt Node für jedes Modul eine Exportvariable bereit, die auf module.exports verweist. Dies entspricht einer Befehlszeile am Kopf jedes Moduls:

var exports = module.exports;(commonJS隐式做了这个赋值)

Der Vorteil davon besteht darin, dass Sie beim Exportieren der Modulschnittstelle Methoden zum Exportobjekt hinzufügen und diese verfügbar machen können.
Wenn Sie also module.exports ändern, aber trotzdem export.xxx verwenden möchten, um etwas verfügbar zu machen, müssen wir selbst exports = module.exports schreiben
Li:

module.exports = songthing;//接下来把exports指回来exports = module.exports;//常见写法是:exports = module.exports = something;

3 . Kompatibilität der AMD-Spezifikation und der CommonJS-Spezifikation

Das Lademodul der CommonJS-Spezifikation ist synchron und erst nach Abschluss des Ladevorgangs können nachfolgende Vorgänge ausgeführt werden. Die AMD-Spezifikation ist ein asynchrones Lademodul, das die Angabe einer Callback-Funktion ermöglicht. Da Node.js hauptsächlich für die Serverprogrammierung verwendet wird, sind Moduldateien im Allgemeinen bereits auf der lokalen Festplatte vorhanden, sodass sie schnell geladen werden können. Es besteht keine Notwendigkeit, ein asynchrones Laden in Betracht zu ziehen, sodass die CommonJS-Spezifikation besser anwendbar ist. Wenn es sich jedoch um eine Browserumgebung handelt und das Modul vom Server geladen werden soll, muss der asynchrone Modus verwendet werden, sodass der Browser in der Regel die AMD-Spezifikation verwendet.

define(['package/lib'], function(lib){  function foo(){
    lib.log('hello world!');
  }  return {    foo: foo
  };
});

Die AMD-Spezifikation ermöglicht die Kompatibilität des Ausgabemoduls mit der CommonJS-Spezifikation. In diesem Fall muss die Definitionsmethode wie folgt geschrieben werden:

define(function (require, exports, module){  var someModule = require("someModule");  var anotherModule = require("anotherModule");
  someModule.doTehAwesome();
  anotherModule.doMoarAwesome();
  exports.asplode = function (){
    someModule.doTehAwesome();
    anotherModule.doMoarAwesome();
  };
});

4.require-Befehl

4.1 Grundlegende Verwendung

Node verwendet die CommonJS-Modulspezifikation und der integrierte Befehl require wird zum Laden von Moduldateien verwendet. Die Grundfunktion des Befehls
require besteht darin, eine JavaScript-Datei zu lesen und auszuführen und dann das Exportobjekt des Moduls zurückzugeben. Wenn das angegebene Modul nicht gefunden wird, wird ein Fehler gemeldet. (Um es ganz klar auszudrücken: Die in einer anderen Datei bereitgestellten Werte werden in dieser Datei referenziert.)

// example.jsvar invisible = function () {  console.log("invisible");
}
exports.message = "hi";
exports.say = function () {  console.log(message);
}

Führen Sie den folgenden Befehl aus, um das Exportobjekt auszugeben.

//someelse.jsvar example = require('./example.js');console.log(example);// {//   message: "hi",//   say: [Function]// }

Wenn das Modul eine Funktion ausgibt, kann diese nicht im Exportobjekt definiert werden, sondern muss in der Variable module.exports definiert werden.

//example2.jsmodule.exports = function () {  console.log("hello world")
}require('./example2.js')()

Im obigen Code ruft sich der Befehl require selbst auf, was der Ausführung von module.exports entspricht, sodass „Hallo Welt“ ausgegeben wird.

4.2 Laderegeln

Der Befehl require wird zum Laden von Dateien verwendet und das Suffix ist standardmäßig .js.

var foo = require('foo');//  等同于var foo = require('foo.js');

Je nach unterschiedlichen Parameterformaten sucht der Befehl require nach Moduldateien in unterschiedlichen Pfaden:

(1) Wenn der Parameter string mit „/“ beginnt ", then Zeigt an, dass eine Moduldatei geladen wird, die sich in einem absoluten Pfad befindet. Beispielsweise lädt require('/home/marco/foo.js') /home/marco/foo.js.
(2) Wenn die Parameterzeichenfolge mit „./“ beginnt, bedeutet dies, dass eine Moduldatei geladen wird, die sich in einem relativen Pfad (im Vergleich zum aktuellen Speicherort der Skriptausführung) befindet. Beispielsweise lädt require('./circle') Circle.js in dasselbe Verzeichnis wie das aktuelle Skript.
(3) Wenn die Parameterzeichenfolge nicht mit „./“ oder „/“ beginnt, bedeutet dies, dass ein standardmäßig bereitgestelltes Kernmodul (im Systeminstallationsverzeichnis von Node) geladen wird, oder ein Modul, das sich in befindet das Verzeichnis node_modules auf allen Ebenen der installierten Module (global oder lokal).

Wenn beispielsweise das Skript /home/user/projects/foo.js den Befehl require('bar.js') ausführt, sucht Node nacheinander nach den folgenden Dateien.

/usr/local/lib/node/bar.js
/home/user/projects/node_modules/bar.js
/home/user/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js

Der Zweck dieses Designs besteht darin, verschiedenen Modulen die Lokalisierung der Module zu ermöglichen, von denen sie abhängen.
(4) Wenn die Parameterzeichenfolge nicht mit „./“ oder „/“ beginnt und ein Pfad ist, wie zum Beispiel require('example-module/path/to/file'), wird example-module gefunden erste Position und verwenden Sie sie dann als Parameter, um den nachfolgenden Pfad zu finden.
(5) Wenn die angegebene Moduldatei nicht gefunden wird, versucht Node vor der Suche, .js, .json und .node zum Dateinamen hinzuzufügen. .js-Dateien werden als textformatierte JavaScript-Skriptdateien analysiert, .json-Dateien werden als JSON-formatierte Textdateien analysiert und .node-Dateien werden als kompilierte Binärdateien analysiert.
(6) Wenn Sie den genauen Dateinamen erhalten möchten, der vom Befehl require geladen wird, verwenden Sie die Methode require.resolve().

4.3 Regeln zum Laden von Verzeichnissen

通常,我们会把相关的文件会放在一个目录里面,便于组织。这时,最好为该目录设置一个入口文件,让require方法可以通过这个入口文件,加载整个目录。
在目录中放置一个package.json文件,并且将入口文件写入main字段。下面是一个例子。

// package.json{ "name" : "some-library",  "main" : "./lib/some-library.js" }
require发现参数字符串指向一个目录以后,会自动查看该目录的package.json文件,然后加载main字段指定的入口文件。如果package.json文件没有main字段,或者根本就没有package.json文件,则会加载该目录下的index.js文件或index.node文件。

4.4模块的缓存

第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。

require('./example.js');require('./example.js').message = "hello";require('./example.js').message// "hello"

上面代码中,连续三次使用require命令,加载同一个模块。第二次加载的时候,为输出的对象添加了一个message属性。但是第三次加载的时候,这个message属性依然存在,这就证明require命令并没有重新加载模块文件,而是输出了缓存。
如果想要多次执行某个模块,可以让该模块输出一个函数,然后每次require这个模块的时候,重新执行一下输出的函数。
所有缓存的模块保存在require.cache之中,如果想删除模块的缓存,可以像下面这样写。

// 删除指定模块的缓存delete require.cache[moduleName];// 删除所有模块的缓存Object.keys(require.cache).forEach(function(key) {  delete require.cache[key];
})

注意,缓存是根据绝对路径识别模块的,如果同样的模块名,但是保存在不同的路径,require命令还是会重新加载该模块。

4.5环境变量NODE_PATH

Node执行一个脚本时,会先查看环境变量NODE_PATH。它是一组以冒号分隔的绝对路径。在其他位置找不到指定模块时,Node会去这些路径查找。

可以将NODE_PATH添加到.bashrc。
export NODE_PATH="/usr/local/lib/node"

所以,如果遇到复杂的相对路径,比如下面这样:

var myModule = require('../../../../lib/myModule');

有两种解决方法,一是将该文件加入node_modules目录,二是修改NODE_PATH环境变量,package.json文件可以采用下面的写法。

{  "name": "node_path",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {    "start": "NODE_PATH=lib node index.js"
  },  "author": "",  "license": "ISC"}

NODE_PATH是历史遗留下来的一个路径解决方案,通常不应该使用,而应该使用node_modules目录机制。

4.6模块的循环加载

如果发生模块的循环加载,即A加载B,B又加载A,则B将加载A的不完整版本。

// a.jsexports.x = 'a1';console.log('a.js ', require('./b.js').x);
exports.x = 'a2';// b.jsexports.x = 'b1';console.log('b.js ', require('./a.js').x);
exports.x = 'b2';// main.jsconsole.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);

上面代码是三个JavaScript文件。其中,a.js加载了b.js,而b.js又加载a.js。这时,Node返回a.js的不完整版本,所以执行结果如下。(也就是说,虽然这样去require看似会造成a.js和b.js循环引用,但commonJS会在将循环的点剪断循环,并对剪断处所在的a.js终止执行,b得到了第一个x值。)

$ node main.js
b.js  a1
a.js  b2
main.js  a2
main.js  b2

修改main.js,再次加载a.js和b.js。

// main.jsconsole.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);console.log('main.js ', require('./a.js').x);console.log('main.js ', require('./b.js').x);

执行上面代码,结果如下。

$ node main.js
b.js  a1
a.js  b2
main.js  a2
main.js  b2
main.js  a2
main.js  b2

上面代码中,第二次加载a.js和b.js时,会直接从缓存读取exports属性,所以a.js和b.js内部的console.log语句都不会执行了。

4.7 require.main

require方法有一个main属性,可以用来判断模块是直接执行,还是被调用执行。
直接执行的时候(node module.js),require.main属性指向模块本身。

require.main === module// true

调用执行的时候(通过require加载该脚本执行),上面的表达式返回false。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

相关阅读:

用jq发送多个ajax然后执行回调的小技巧

怎样使用伪元素first-letter让文字首字母大写

JavaScript的函数重载详解

chrome的内存不足频繁崩溃怎么处理

Das obige ist der detaillierte Inhalt vonAusführliche Erklärung von commonJS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn