Non, le module ES6 génère une référence à la valeur, tandis que le module CommonJS génère une copie de la valeur. Dans le module ES6, lorsque le moteur JS analyse statiquement le script et rencontre la commande de chargement du module import, il génère une référence en lecture seule ; lorsque le script est réellement exécuté, il ira au module chargé en fonction de cette référence en lecture seule ; référence. Prendre de la valeur. Les modules ES6 sont des références dynamiques. Les modules ES6 ne mettent pas en cache les résultats en cours d'exécution, mais obtiennent dynamiquement les valeurs du module chargé, et les variables sont toujours liées au module dans lequel elles se trouvent.
L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.
Par défaut, le navigateur charge les scripts JavaScript de manière synchrone, c'est-à-dire que lorsque le moteur de rendu rencontre la balise
<script>
, il s'arrêtera et attendra que exécution Terminez le script et continuez le rendu.<script>
标签就会停下来,等到执行完脚本,再继续向下渲染。
如果是外部脚本,还必须加入脚本下载的时间。
如果脚本体积很大,下载和执行的时间就会很长,因此造成浏览器堵塞,用户会感觉到浏览器“卡死”了,没有任何响应。这显然是很不好的体验,所以浏览器允许脚本异步加载,下面就是两种异步加载的语法。
<script src="path/to/myModule.js" defer></script> <script src="path/to/myModule.js" async></script>
<script>
标签打开defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令。
defer
要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async
一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
浏览器加载 ES6 模块,也使用<script>
标签,但是要加入type="module"
属性。浏览器对于带有type="module"
的<script>
,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了
<script type="module" src="./foo.js"></script>
如果网页有多个,它们会按照在页面出现的顺序依次执行。
注意:
<script>
标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染。一旦使用了async属性,就不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。
对于外部的模块脚本(上例是foo.js),有几点需要注意:
undefined
<script type="module"> import utils from "./utils.js"; // other code </script>
<script>
active l'attribut defer ou async et le script sera chargé de manière asynchrone. Lorsque le moteur de rendu rencontrera cette ligne de commande, il commencera à télécharger le script externe .
defer
ne sera pas exécuté tant que la page entière n'est pas rendue normalement en mémoire (la structure DOM est complètement générée et d'autres scripts sont exécutés async
) ; Une fois téléchargé, le moteur de rendu interrompra le rendu et poursuivra le rendu après l'exécution de ce script. . De plus, s'il existe plusieurs scripts de report, ils seront chargés dans l'ordre dans lequel ils apparaissent sur la page, mais plusieurs scripts asynchrones ne peuvent pas garantir l'ordre de chargement.Le navigateur charge le module ES6 et utilise également la balise
, ce qui équivaut à ouvrir 🎜<script>
, mais l'attributtype="module"
doit être ajouté. Le navigateur charge<script>
avectype="module"
de manière asynchrone, ne bloquera pas le navigateur, c'est-à-dire qu'il attendra que la page entière soit rendue. Après cela, exécuter le script du module🎜Si la page Web comporte plusieurs// lib.js export let obj = {}; // main.js import { obj } from './lib'; obj.prop = 123; // OK obj = {}; // TypeErrorCopier après la connexionCopier après la connexion, ils seront exécutés dans l'ordre 🎜dans l'ordre dans lequel ils apparaissent la page🎜 . 🎜🎜🎜Remarque : L'attribut asynchrone de la balise
<script>
peut également être activé à ce moment-là, tant que le chargement est terminé, le moteur de rendu interrompra le rendu et l'exécutera. immédiatement. Une fois l'exécution terminée, reprenez le rendu. Une fois l'attribut async utilisé,🎜 ne sera pas exécuté dans l'ordre dans lequel il apparaît sur la page, mais sera exécuté tant que le module est chargé. 🎜🎜🎜🎜Pour les scripts de module externes (l'exemple ci-dessus est foo.js), il y a quelques points à noter : 🎜
🎜Le code 🎜s'exécute dans la portée du module🎜, pas dans la portée globale. Les variables de niveau supérieur à l'intérieur du module ne sont pas visibles de l'extérieur. 🎜🎜Le script du module 🎜adopte automatiquement le mode strict🎜, que use strict soit déclaré ou non. 🎜🎜Dans le module, vous pouvez utiliser la commande import pour charger d'autres modules (le suffixe 🎜.js ne peut pas être omis, vous devez fournir une URL absolue ou une URL relative🎜), ou vous pouvez utiliser la commande export pour afficher le fichier externe. interface. 🎜🎜Dans le module, le mot-clé de niveau supérieur this renvoie
undefined
au lieu de pointer vers la fenêtre. En d’autres termes, utiliser ce mot-clé au niveau supérieur d’un module n’a aucun sens. 🎜🎜🎜Si le même module est chargé plusieurs fois, il ne sera exécuté qu'une seule fois🎜. 🎜🎜🎜🎜Les modules ES6 peuvent également être intégrés dans des pages Web, et le comportement syntaxique est exactement le même que celui du chargement de scripts externes. 🎜rrreee🎜🎜La différence entre les modules ES6 et les modules CommonJS🎜🎜🎜🎜CommonJS est un module de chargement synchrone, ES6 est un module de chargement asynchrone🎜🎜🎜🎜🎜Le module de chargement de spécification CommonJS est synchrone🎜, c'est-à-dire,🎜Seulement lorsque le chargement est terminé, vous pouvez effectuer les opérations suivantes🎜. Étant donné que Node.js est principalement utilisé pour la programmation du serveur, les fichiers de module existent généralement déjà sur le disque dur local, ils peuvent donc être chargés rapidement. Il n'est pas nécessaire d'envisager un chargement asynchrone, la spécification CommonJS est donc plus applicable. 🎜
但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用异步模式。
浏览器加载 ES6 模块是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本
CommonJS 模块
输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值
ES6 模块
的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,ES6 模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。
由于 ES6 输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。上面代码中,main.js从lib.js输入变量obj,可以对obj添加属性,但是重新赋值就会报错。因为变量obj指向的地址是只读的,不能重新赋值,这就好比main.js创造了一个名为obj的const变量。
// lib.js export let obj = {}; // main.js import { obj } from './lib'; obj.prop = 123; // OK obj = {}; // TypeError
此外,export通过接口,输出的是同一个值。不同的脚本加载这个接口,得到的都是同样的实例。
因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。
而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
【相关推荐:javascript视频教程、编程视频】
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!