当前位置: 首页 > news >正文

河北省住房和城乡建设局网站html网站开发语言

河北省住房和城乡建设局网站,html网站开发语言,大学生家教网站开发,横峰县城乡建设网站#x1f601; 作者简介#xff1a;一名大四的学生#xff0c;致力学习前端开发技术 ⭐️个人主页#xff1a;夜宵饽饽的主页 ❔ 系列专栏#xff1a;JavaScript进阶指南 #x1f450;学习格言#xff1a;成功不是终点#xff0c;失败也并非末日#xff0c;最重要的是继… 作者简介一名大四的学生致力学习前端开发技术 ⭐️个人主页夜宵饽饽的主页 ❔ 系列专栏JavaScript进阶指南 学习格言成功不是终点失败也并非末日最重要的是继续前进的勇气 ​​前言 本篇是关于上一章中的js模块语法使用的原理解析里面有一个需要小伙伴们注意的点就是循环加载模块的原理和解决办法这部分大家可以重点理解,希望可以帮助到大家欢迎大家的补充和纠正 JavaScript中的模块Module语法的使用细节export命令和imprt命令详细使用 文章目录 第23章 Module的加载实现23.1 浏览器加载23.1.1 传统方法23.1.2 加载规则 23.2 ES6模块与CommonJS模块的差异23.3 Node加载23.3.1 概述23.3.2 import命令加载CommonJS模块23.3.3 require命令加载ES6模块 23.4 循环加载23.4.1 CommonJS模块的加载原理23.4.2 CommonJS模块循环加载23.4.3 ES6模块的循环加载 第23章 Module的加载实现 23.1 浏览器加载 23.1.1 传统方法 默认情况下浏览器同步加载JavaScript脚本即渲染引擎遇到 script 标签就会停下来等到脚本执行完毕再继续向下渲染如果是外部脚本还必须加入脚本下载的时间 如果脚本体积很大下载和执行的时间就会很长因此造成浏览器堵塞用户会感觉到浏览器卡死了没有任何响应这显然是很不好的体验所以浏览器允许脚本异步加载下面就是两种异步加载的语法 script srcpath/to/myModule.js defer/script script srcpath/to/myModule.js async/script上面这个代码中 script 标签打开defer或者async属性脚本就会异步加载渲染引擎遇到这一行命令会开始下载脚本但不会等它下载和执行而是直接执行后面的命令。 defer 与 async的区别是 defer等到整个页面正常渲染结束才会执行如果出现多个则按照它们在页面出现的顺序加载一句话概括就是先渲染完再执行async一旦下载完成渲染引擎就会中断渲染执行这个脚本以后再继续渲染如果出现多个则不能保证其加载顺序一句话概括就是下载完执行 23.1.2 加载规则 浏览器加载ES6模块时也使用 script 标签但是要加入typemodule属性 script typemodule srcfoo.js/script上面的代码在网页中插入一个模块foo.js由于type属性设为module所以浏览器知道这是一个ES6模块 对于带有typemodule的 script 浏览器都是异步加载的不会造成浏览器堵塞即等到整个页面渲染完再执行模块脚本等同于打开了 script 标签的defer属性。 script typemodule srcfoo.js/script!-- 等同于 -- script typemodule srcfoo.js defer/scriptscript 标签的async属性也可以打开这时只要加载完成渲染引擎就会中断渲染立即执行执行完成后再恢复渲染 script typemodule srcfoo.js async/scriptES6模块也允许内嵌在网页中语法行为与外部脚本完全一致 对于外部的模块脚本上例是foo.js有几点需要注意 代码是在模块作用域之中运行的而不是在全局作用域中运行的模块内部的顶层变量是外部不可见模块脚本自动采用严格模式无论有没有声明use strict模块之中可以使用import命令加载其他模块.js后缀不可省略需要提供绝对URL或相对的URL)也可以使用export命令输出对外接口在模块之中顶层的this关键字返回undefined而不是指向window也就是说在模块顶层使用this关键字是无意义的同一个模块如果加载多次将只执行一次 23.2 ES6模块与CommonJS模块的差异 讨论Node加载ES6模块之前必须了解ES6模块与CommonJS模块的差异具体的两大差异如下 CommonJS模块输出的是一个值的复制ES6模块模块输出是值的引用CommonJS模块是运行时加载的ES6模块是编译时输出接口 第二个差异是因为CommonJS加载的是一个对象即module.exports属性该对象只有在脚本运行结束时才会生成而ES6模块不是对象它的对外接口只是一种静态定义在代码静态解析阶段就会生成 我们来重点解释第一个差异 CommonJS模块输出的是值得复制也就是说一旦输出一个值模块内部的变化就影响不到这个值请看下面这个模块文件lib.js的例子 //lib.js var counter 3 function incCounter(){counter }module.export{counter:counter,incCounter:incCounter }//main.js var modrequire(./lib)console.log(mod.counter) //3 mod.incCounter() console.log(mod.counter) //3上面的代码说明lib.js模块加载以后它的内部变化就影响不到输出的mod.counter了。这是因为mod.counter是一个原始类型的值会被缓存除非写成一个函数否则得不到内部变动后的值 //lib.js var counter3 function inCounter(){counter }module.exports{get counter(){return counter},incCounter:incCounter }上面的代码中输出的counter属性实际上是一个取值器函数现在再执行main.js就可以正确读取内部变量counter的变动 ES6模块的运行机制与CommonJS不一样JS引擎对脚本静态分析的时候遇到模块加载命令import就会生成一个只读引用等到脚本真正执行时再根据这个只读引用到被加载的模块中取值。 //lib.js var counter 3 function incCounter(){counter }module.export{counter:counter,incCounter:incCounter }//main.js import {counter,incCounter} from ./libconsole.log(counter) //3 incCounter() console.log(counter) //4使用细节 ES6模块不会缓存运行结果而是动态地去被加载的模块取值并且变量总是绑定在其所在的模块由于ES6输入的模块变量只是一个符号引用所以这个变量是只读不同脚本加载这个接口得到的都是同样的实例 23.3 Node加载 23.3.1 概述 Node对ES6模块处理比较麻烦因为其有自己的CommonJS模块格式与ES6模块格式是不兼容的目前的解决方案将两者分开。 在静态分析阶段一个模块只要有一行import后者export语句那么Node采用ES6模块否则就为CommonJS模块 如果我们不输出任何接口但是希望被Node认为是ES6模块可以这么写 export {}上面的代码中并不是输出一个空对象而是不输出任何接口的ES6标准写法 23.3.2 import命令加载CommonJS模块 使用import命令加载CommonJS模块Node将自动将module.export属性当作模块的默认输出即等同于export default //a.js module.export{foo:hello,bar:world }//等同于 export default{foo:hello,bar:world }//写法一 import baz from ./a baz{foo:hello,bar:world}//写法二 import {default as baz} from ./a baz{foo:hello,bar:world}⭐️ 如果采用整体输入的写法会与上面稍微不同default会取代module.export作为输入的接口 import * as baz from ./a/** baz{get default(){return module.exports},get foo(){return this.default.foo}.bind(baz)get bar(){return this.default.bar}.bind(baz) }**/上面的代码中this.default取代了module.export。需要注意的是Node会自动取代为baz添加default属性通过baz.default获取module.exports 在看下面这个代码会让你更加清晰 //c.js module.exportfunction two(){return 2 }//es.js import foo from ./c foo() //2import * as bar from ./c bar.default() //2 bar() //throw ,bar is not a function❗️ 注意由于ES6模块编译时确定输出接口CommonJS模块是运行时确定输出接口所以采用import命令加载CommonJS模块时不允许采用下面的写法 import {readfile} from fs23.3.3 require命令加载ES6模块 ES6模块的所有输出接口都会称为输入对象的属性 //es.js export let foo{bar:my_default} export {foo as bar} export function f(){} export class c{}//cjs.js const es_namespacerequire(./es) /** es_namespace{get foo(){return foo}get bar(){return foo}get f(){return f}get c(){return c} } **/23.4 循环加载 “循环加载”指的是a脚本的执行依赖b脚本而b脚本的执行依赖a脚本 //a.js var brequire(b)//b.js var arequire(a)通常“循环加载” 表示存在强耦合如果处理不好还可能导致递归加载使得程序无法执行 因此应该避免出现这种现象 但是实际上 这是很难避免的尤其是依赖关系复杂的大项目中很容易出现a依赖b,b依赖cc又依赖a这样的情况这意味着模块加载机制必须考虑循环加载的情况 23.4.1 CommonJS模块的加载原理 CommonJS的模块就是一个脚本文件require命令第一次加载该脚本时就会执行整个脚本然后内存中生成一个对象 {id:...,exports:{ ... },loaded:true }上面的代码就是Node内部加载模块后生成的一个对象该对象的id属性是模块名exports属性是模块输出的各个接口loaded属性表示该脚本是否执行完毕是一个布尔值 以后需要用到这个值时会在export属性中取值即使再次执行require命令也不会再次执行该模块而是去缓存中取值也就是说CommonJS模块无论加载多少次都只会在第一次加载时运行一次以后再加载时就会返回第一次运行的结果除非手动清除系统缓存 小知识关于如何手动清除系统缓存 /** 使用delete操作符清除缓存:你可以使用delete操作符从require方法的require.cache对象中删除特定模块的缓存。例如假设你要清除名为my-module的模块的缓存可以这样做 **/ delete require.cache[require.resolve(./my-module)]; //这将从模块缓存中删除指定模块的缓存下次引入这个模块时将重新加载它。/** 使用module.constructor._cache清除缓存:另一种方法是直接访问module.constructor._cache对象这是Node.js内部用来存储模块缓存的对象。同样你可以通过删除特定模块的缓存来清除它。例如 **/ delete require(module)._cache[require.resolve(./my-module)]; //这也将清除指定模块的缓存。/** 清除所有模块的缓存:如果你需要一次性清除所有模块的缓存可以使用以下方法 **/ Object.keys(require.cache).forEach(function(key) {delete require.cache[key]; }); //这将遍历所有模块的缓存并将它们全部删除。23.4.2 CommonJS模块循环加载 CommonJS模块的重要特性是加载时运行即脚本代码在require的时候会全部执行。 一旦出现某一个模块被“循环加载”就只输出已经执行的部分还未执行的部分不会输出。 接下里我们来看一下Node官方文档的例子 脚本文件a.js代码如下 export.donefalse var brequire(./b.js) console.log(在a.js之中b.done%j,b.done) export.donetrue console.log(a.js执行完毕)上面的代码之中a.js脚本先输出一个done变量然后加载另一个脚本文件b.js注意此时a.js代码就停在这里等待b.js执行完毕再执行 脚本文件b.js代码如下 export.donefalse var arequire(./a.js) console.log(在b.js之中a.done%j,a.done) export.donetrue console.log(b.js执行完毕)上面的代码中b.js执行到第二行就会加载a.js这时就发生了“循环加载”系统就去a.js模块对应对象的export属性中取值可是a.js并没有执行完因此从exports属性中只能取到已经执行的部分而不是最后的值 //a.js执行的部分代码如下 export.donefalse因此对于b.js来说它从a.js只输入一个变量done值为false 然后b.js接着执行等到全部执行完毕再把执行权交还给a.js。于是a.js接着执行直到执行完毕下面我们是输出结果 //在b.js之中a.donefalse //b.js执行完毕 //在a.js之中b.donetrue //a.js执行完毕 //在main.js之中a.donetrue,b.donetrue代码思路图解 上面的代码证明了两件事第一在b.js之中a.js没有执行完毕只执行了第一行。第二reimain.js执行到第二行时不会再次执行b.js而是输出缓存的b.js的执行结果即它的第四行。 ⭐️ 一点非常实用的小建议 由于CommonJS模块遇到循环加载时返回的是当前已经执行的部分值而不是代码全部执行的值两者可能会有差异所以输入变量的时候必须非常小心 var arequire(a) //安全的写法 var foorequire(a).foo //危险的写法export.goodfunction(arg){return a.foo(good,arg) //使用的是a.foo的最新值 }export.badfunction(arg){return foo(bad,arg) //使用的是一个部分加载时的值 }23.4.3 ES6模块的循环加载 ES6处理“循环加载”与CommonJS有本质的不同。ES6模块是动态引用如果使用import从一个模块中加载变量即import foo from ‘foo’)那么变量不会被缓存而是成为一个指向被加载模块的引用需要开发者保证在真正取值的时候能够取到值。 接下里有两个经典代码例子 简单文件模块执行 //a.js import {bar} from ./b.js console.log(a.js) console.log(bar) export let foofoo//b.js import {foo} from ./a.js console.log(b.js) console.log(foo) export let barbar//执行结果 //b.js //undefined //a.js //bar上面的代码中由于a.js的第一行是加载b.js所以先执行的是b.js。而b.js的第一行又是加载a.js这时由于a.js已经开始执行所以不会重复执行而是继续执行b.js 因此第一行输出b.js 接着b.js要打印变量foo这时a.js还没有执行完取不到foo的值因此打印出来undefinedb.js执行完便会开始执行a.js这时一切会正常 复杂函数文件模块执行 //a.js import {bar} from ./b.js export function foo(){console.log(foo);bar()console.log(执行完毕) } foo()//b.js import {foo} from ./a.js export function bar(){console.log(bar)if(Math.random() 0.5){foo()} }// 执行结果有两种可能 // 第一种 // foo // bar // 执行完毕// 第二种 // foo // bar // foo // bar // 执行完毕 // 执行完毕上面的代码中a.js之所以能够执行原因就在于ES6加载的变量都是动态引用其所在模块只要引用存在就可以执行 如果上面代码按照CommonJS规范上面的代码时无法执行的a先加载b然后b又加载a这时a还没有任何执行结果所以输出结果为null即对于b.js来说变量foo的值等于null后面的foo()就会报错
http://www.pierceye.com/news/45320/

相关文章:

  • 东莞做网站dgjcwl做网站公司青岛
  • 国内漂亮大气的网站南昌做微网站
  • 上海建设银行长宁区各分行网站wordpress免费教程
  • 福田我要做网站优化比较好比较大气的网站
  • 企业外贸网站网页制作标准
  • 做网站网页需要学些什么wordpress 迁移 空白
  • 建设网站有哪些方法宁波网站的优化
  • 营销型网站制作培训wordpress获得分类下的子分类
  • 做债的网站安阳青峰网站建设
  • 学习电子商务网站建设与管理的收获设计师的网站
  • 淘宝网请人做淘宝客网站做网站的s标的软件
  • 珠海网站搭建温岭网站建设联系电话
  • jsp网站模版南宁住房和城乡建设部网站
  • 邯郸网站设计培训机构搜狗营销
  • 电商网站 厦门wordpress 黄蓝 现代企业
  • 娄底网站建设报价php 数据库转wordpress
  • 天津搜索引擎优化seo怎么去优化
  • 东莞网站定制设计说明书怎么写
  • 山东平台网站建设价位莱州人才网
  • 网站建设工作进度计划表网站建设制作品牌公司
  • 如何免费建一个学校网站宿迁网站建设报价
  • net网站建设入门教程重庆建设厅官方网站
  • 网站地图怎么做国外网站域名备案
  • aspcms 网站无法显示该页面郑州seo公司哪家好
  • pinterest设计网站成都旅游攻略四天三夜
  • php做的卖水果网站网络营销方式变化背后的逻辑与趋势
  • 淘宝客网站怎么建设电子商务网站建设与管理心得
  • asp.net mvc 企业网站手机免费制作软件下载
  • 网站的分辨率企业网站开发韵茵
  • 网站做过备案后能改别的公司吗以企业介绍为主做外贸网站好吗