专业做英文网站,通州网站开发,如何制造公司网站,宿州做网站1.浏览器加载
1.1传统方法#xff1a;
在 HTML 网页中#xff0c;浏览器通过script标签加载 JavaScript 脚本
默认情况下#xff0c;浏览器是同步加载 JavaScript 脚本#xff0c;即渲染引擎遇到script标签就会停下来#xff0c;等到执行完脚本…1.浏览器加载
1.1传统方法
在 HTML 网页中浏览器通过script标签加载 JavaScript 脚本
默认情况下浏览器是同步加载 JavaScript 脚本即渲染引擎遇到script标签就会停下来等到执行完脚本再继续向下渲染。如果是外部脚本还必须加入脚本下载的时间
如果脚本体积很大下载和执行的时间就会很长因此造成浏览器堵塞用户会感觉到浏览器“卡死”了没有任何响应。这显然是很不好的体验所以浏览器允许脚本异步加载下面就是两种异步加载的语法 上面代码中script标签打开defer或async属性脚本就会异步加载。渲染引擎遇到这一行命令就会开始下载外部脚本但不会等它下载和执行而是直接执行后面的命令
defer与async的区别是前者要等到整个页面正常渲染结束才会执行后者一旦下载完渲染引擎就会中断渲染执行这个脚本以后再继续渲染。一句话defer是“渲染完再执行”async是“下载完就执行”。另外如果有多个defer脚本会按照它们在页面出现的顺序加载而多个async脚本是不能保证加载顺序的
1.2加载规则
浏览器加载 ES6 模块也使用script标签但是要加入type”module”属性
上面代码在网页中插入一个模块foo.js由于type属性设为module所以浏览器知道这是一个 ES6 模块
浏览器对于带有type”module”的script都是异步加载不会造成堵塞浏览器即等到整个页面渲染完再执行模块脚本等同于打开了script标签的defer属性
script标签的async属性也可以打开这时只要加载完成渲染引擎就会中断渲染立即执行。执行完成后再恢复渲染 ES6 模块也允许内嵌在网页中语法行为与加载外部脚本完全一致
对于外部的模块脚本上例是foo.js有几点需要注意 - 代码是在模块作用域之中运行而不是在全局作用域运行。模块内部的顶层变量外部不可见 - 模块脚本自动采用严格模式不管有没有声明use strict - 模块之中可以使用import命令加载其他模块.js后缀不可省略需要提供绝对 URL 或相对 URL也可以使用export命令输出对外接口 - 模块之中顶层的this关键字返回undefined而不是指向window。也就是说在模块顶层使用this关键字是无意义的 - 同一个模块如果加载多次将只执行一次
下面是一个示例模块
利用顶层的this等于undefined这个语法点可以侦测当前代码是否在 ES6 模块之中
2.ES6 模块与 CommonJS 模块的差异
CommonJS 模块输出的是一个值的拷贝ES6 模块输出的是值的引用CommonJS 模块是运行时加载ES6 模块是编译时输出接口
第二个差异是因为 CommonJS 加载的是一个对象即module.exports属性该对象只有在脚本运行完才会生成。而 ES6 模块不是对象它的对外接口export只是一种静态定义在代码静态解析阶段就会生成
下面重点解释第一个差异
CommonJS 模块输出的是值的拷贝也就是说一旦输出一个值模块内部的变化就影响不到这个值。请看下面这个模块文件lib.js的例子
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候遇到模块加载命令import就会生成一个对输出模块的只读引用等到脚本真正要用到模块输出的方法时再根据这个只读引用到被加载的那个模块里面去取值。换句话说ES6 的import有点像 Unix 系统的“符号连接”原始值变了import加载的值也会跟着变。因此ES6 模块是动态引用并且不会缓存值模块里面的变量绑定其所在的模块 上面代码说明ES6 模块输入的变量counter是活的完全反应其所在模块lib.js内部的变化 上面代码表明ES6 模块不会缓存运行结果而是动态地去被加载的模块取值并且变量总是绑定其所在的模块
由于 ES6 输入的模块变量只是一个“符号连接”所以这个变量是只读的对它进行重新赋值会报错
上面代码中main.js从lib.js输入变量obj可以对obj添加属性但是重新赋值就会报错。因为变量obj指向的地址是只读的不能重新赋值这就好比main.js创造了一个名为obj的const变量
最后export通过接口输出的是同一个值。不同的脚本加载这个接口得到的都是同样的实例 这就证明了x.js和y.js加载的都是C的同一个实例