>  기사  >  웹 프론트엔드  >  es6 모듈에서 출력된 값이 복사되나요?

es6 모듈에서 출력된 값이 복사되나요?

青灯夜游
青灯夜游원래의
2022-10-18 15:29:561033검색

아니요, ES6 모듈은 값에 대한 참조를 출력하는 반면 CommonJS 모듈은 값의 복사본을 출력합니다. ES6 모듈에서는 JS 엔진이 스크립트를 정적으로 분석하고 모듈 로딩 명령 import를 발견하면 스크립트가 실제로 실행될 때 이 읽기 전용 참조를 기반으로 로드된 모듈로 이동합니다. 참고하세요. ES6 모듈은 동적 참조입니다. ES6 모듈은 실행 결과를 캐시하지 않지만 로드된 모듈에서 값을 동적으로 가져오며 변수는 항상 해당 모듈이 위치한 모듈에 바인딩됩니다.

es6 모듈에서 출력된 값이 복사되나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, ECMAScript 버전 6, Dell G3 컴퓨터.

브라우저 로딩

기본적으로 브라우저는 JavaScript 스크립트를 동기적으로 로드합니다. 즉, 렌더링 엔진이 3f1c4e4b6b16bbbd69b2ee476dc4f83a 태그를 발견하면 중지하고 다음이 될 때까지 기다립니다. 실행 스크립트를 완료하고 렌더링을 계속합니다. 3f1c4e4b6b16bbbd69b2ee476dc4f83a标签就会停下来,等到执行完脚本,再继续向下渲染。

如果是外部脚本,还必须加入脚本下载的时间。

如果脚本体积很大,下载和执行的时间就会很长,因此造成浏览器堵塞,用户会感觉到浏览器“卡死”了,没有任何响应。这显然是很不好的体验,所以浏览器允许脚本异步加载,下面就是两种异步加载的语法。

<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>

3f1c4e4b6b16bbbd69b2ee476dc4f83a标签打开defer或async属性,脚本就会异步加载。渲染引擎遇到这一行命令,就会开始下载外部脚本,但不会等它下载和执行,而是直接执行后面的命令

  • defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;
  • async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。

一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。

浏览器加载 ES6 模块,也使用3f1c4e4b6b16bbbd69b2ee476dc4f83a标签,但是要加入type="module"属性。浏览器对于带有type="module"3f1c4e4b6b16bbbd69b2ee476dc4f83a,都是异步加载不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了

a907279e6cf2b736e22e16a7121cae332cacc6d41bbb37262a98f745aa00fbf0

如果网页有多个f8666432049ee9d811f748637f7d3a4b,它们会按照在页面出现的顺序依次执行

注意:3f1c4e4b6b16bbbd69b2ee476dc4f83a标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染。一旦使用了async属性,f8666432049ee9d811f748637f7d3a4b就不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。

对于外部的模块脚本(上例是foo.js),有几点需要注意:

  • 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见。
  • 模块脚本自动采用严格模式,不管有没有声明use strict。
  • 模块之中,可以使用import命令加载其他模块(.js后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用export命令输出对外接口。
  • 模块之中,顶层的this关键字返回undefined
  • 외부 스크립트인 경우 스크립트 다운로드 시간도 추가해야 합니다. 스크립트의 크기가 크면 다운로드 및 실행에 시간이 오래 걸리므로 브라우저가 차단되고 사용자는 아무런 응답 없이 브라우저가 '멈춘다'는 느낌을 받게 됩니다. 이는 분명히 매우 나쁜 경험이므로 브라우저는 스크립트의 비동기 로딩을 허용합니다. 다음은 비동기 로딩을 위한 두 가지 구문입니다.
3acaf50c6526a47d62726f112635bc51
  import utils from "./utils.js";
  // other code
2cacc6d41bbb37262a98f745aa00fbf0
3f1c4e4b6b16bbbd69b2ee476dc4f83a 태그는 defer 또는 async 속성을 활성화하고 스크립트는 비동기적으로 로드됩니다. 렌더링 엔진이 이 명령줄을 만나면 외부 스크립트를 다운로드하기 시작하지만
다운로드 및 실행을 기다리지 않고 다음 명령

을 직접 실행합니다.

    defer는 전체 페이지가 메모리에서 정상적으로 렌더링될 때까지 실행되지 않습니다(DOM 구조가 완전히 생성되고 다른 스크립트가 실행됨). async 다운로드되면 렌더링 엔진이 렌더링을 중단하고 이 스크립트를 실행한 후 렌더링을 계속합니다.

    한 문장에서

    defer는 "렌더링 후 실행"을 의미하고 async는 "다운로드 후 실행"
    을 의미합니다. 또한 defer 스크립트가 여러 개인 경우 페이지에 나타나는 순서대로 로드되지만 비동기 스크립트가 여러 개 있으면 로드 순서를 보장할 수 없습니다.

    브라우저는 ES6 모듈을 로드하고 3f1c4e4b6b16bbbd69b2ee476dc4f83a 태그도 사용하지만 type="module" 속성을 ​​추가해야 합니다. 브라우저는 type="module" 비동기식으로 3f1c4e4b6b16bbbd69b2ee476dc4f83a를 로드하며 브라우저를 차단하지 않습니다. 즉, 전체 페이지가 렌더링될 때까지 기다립니다. 그 후,

    // lib.js
    export let obj = {};
    // main.js
    import { obj } from './lib';
    obj.prop = 123; // OK
    obj = {}; // TypeError
    🎜를 여는 것과 동일한 모듈 스크립트 🎜를 실행합니다. 웹페이지에 e91f03099790807ac093726dd6cff003이 여러 개 있으면 표시된 순서대로 🎜실행됩니다. 페이지🎜 . 🎜🎜🎜참고: 3f1c4e4b6b16bbbd69b2ee476dc4f83a 태그의 비동기 속성도 설정할 수 있습니다. 이때 로딩이 완료되면 렌더링 엔진이 렌더링을 중단하고 실행합니다. 즉시. 실행이 완료되면 렌더링을 재개합니다. async 속성을 사용하면 e91f03099790807ac093726dd6cff003🎜는 페이지에 표시된 순서대로 실행되지 않고, 모듈이 있는 동안에는 실행됩니다. 짐을 실은. 🎜🎜🎜🎜외부 모듈 스크립트(위의 예는 foo.js)의 경우 몇 가지 참고할 사항이 있습니다. 🎜
      🎜코드는 🎜전역 범위가 아닌 모듈 범위🎜에서 실행됩니다. 모듈 내부의 최상위 변수는 외부에 표시되지 않습니다. 🎜🎜모듈 스크립트는 use strict 선언 여부에 관계없이 자동으로 🎜엄격 모드를 채택🎜합니다. 🎜🎜모듈에서 import 명령을 사용하여 다른 모듈을 로드할 수 있습니다(🎜.js 접미사는 생략할 수 없으며 절대 URL 또는 상대 URL을 제공해야 합니다🎜). 또는 내보내기 명령을 사용하여 외부 모듈을 출력할 수 있습니다 인터페이스. 🎜🎜모듈에서 최상위 this 키워드는 창을 가리키는 대신 unjust를 반환합니다. 즉, 모듈의 최상위 수준에서 이 키워드를 사용하는 것은 의미가 없습니다. 🎜🎜🎜동일한 모듈이 여러 번 로드되면 한 번만 실행됩니다🎜. 🎜🎜🎜🎜ES6 모듈은 웹 페이지에 포함될 수도 있으며 구문 동작은 외부 스크립트를 로드하는 것과 정확히 동일합니다. 🎜rrreee🎜🎜ES6 모듈과 CommonJS 모듈의 차이점🎜🎜🎜🎜CommonJS는 동기 로딩 모듈이고, ES6은 비동기 로딩 모듈입니다.🎜🎜🎜🎜🎜CommonJS 사양 로딩 모듈은 동기적입니다🎜. 즉, 🎜다음과 같은 경우에만 로딩이 완료되면 다음 작업을 수행할 수 있습니다🎜. Node.js는 주로 서버 프로그래밍에 사용되기 때문에 모듈 파일은 일반적으로 로컬 하드 디스크에 이미 존재하므로 빠르게 로드할 수 있으므로 비동기 로딩을 고려할 필요가 없으므로 CommonJS 사양이 더 적합합니다. 🎜

    但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用异步模式

    浏览器加载 ES6 模块是异步加载不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本


    CommonJS 模块输出的是一个值的拷贝,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 模块是运行时加载,ES6 模块是编译时输出接口。

因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成

而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成

【相关推荐:javascript视频教程编程视频

위 내용은 es6 모듈에서 출력된 값이 복사되나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.