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

网站建设方案报价表温州建网站哪家强

网站建设方案报价表,温州建网站哪家强,阿里云可以做网站吗,淘宝客做网站还是做app1. generator#xff08;生成器#xff09; 详细介绍 generator 介绍 generator 是 ES6 提供的一种异步编程解决方案#xff0c;在语法上#xff0c;可以把它理解为一个状态机#xff0c;内部封装了多种状态。执行generator#xff0c;会生成返回一个遍历器对象。返回的…1. generator生成器 详细介绍 generator 介绍 generator 是 ES6 提供的一种异步编程解决方案在语法上可以把它理解为一个状态机内部封装了多种状态。执行generator会生成返回一个遍历器对象。返回的遍历器对象可以依次遍历generator函数的每一个状态。同时 ES6 规定这个遍历器是Generator函数的实例也继承了 Genarator函数的 prototype 对象上的方法 最简单的generator函数,其实它就是一个普通的函数但是它有两个特征 第一就是function关键字与函数名之间有一个*号其二就是函数体内使用yield表达式来遍历状态 function* newGenerator() {yield hello;yield world;return ending; }执行 generator 函数之后该函数并不会立即执行返回的也不是函数运行结果而是一个指向内部状态的指针对象。通常使用遍历器对象的 next 方法。使得指针移向下一个状态。每一次调用 next() 方法内部指针就从函数头部或上一次停下来的地方开始执行直到遇到下一个 yield 表达式位置由此可以看出generator 是分段执行的yield 表达式是暂停执行的标记而next方法可以恢复执行 【注generator函数可以随心所欲的交出和恢复函数的执行权yield 交出执行权next() 恢复执行权】 yield yield 表达式在 generator 中是作为一个暂停标志当碰到 yield 时函数暂停执行。等到下一次 next() 执行时函数才从当前 yield 位置开始执行。并且yield表达式只能用在 Generator 函数里边。同时yield 如果后边带一个 *则就是相当于一个 for…of 的简写形式如果 yield 后边不带 *则返回的是 generator 的值function* gen() {yield hello;yield* hello; } let f gen(); console.log(f.next().value); // hello console.log(f.next().value); // h console.log(f.next().value); // e console.log(f.next().value); // l console.log(f.next().value); // l console.log(f.next().value); // o无论是触发了 yield 还是 returnnext() 函数总会返回一个带有 value 和 done 属性的对象value 为返回值done 则是一个Boolean 对象用来标识 Generator 是否还能继续提供返回值function * oddGenerator () {yield 1yield 3return 5 } let iterator oddGenerator() let first iterator.next() // { value: 1, done: false } let second iterator.next() // { value: 3, done: false } let third iterator.next() // { value: 5, done: true }nextthrowreturn 以上的三个方法在本质上其实是一样的就是让 generator 恢复执行并且使用不同的语句来替代 yield 语句 next() 是将 yield 表达式替换成一个值throw() 是将 yield 表达式替换成一个 throw 语句return() 是将 yield 表达式替换成一个 return 语句 例 function* dataConsumer() {console.log(Started);console.log(1. ${yield});console.log(2. ${yield});return result; } let genObj dataConsumer(); genObj.next(); // Started genObj.next(a); // 1. a genObj.next(b); // 2. byield test() 时值是还没有确定的什么时候会确定呢就是执行下一次 next 方法时通过传参数 next(val) 的方式来确定值什么意思呢看下面这段代码 const test () new Promise((resolve,reject) setTimeout(() {resolve(test)},1000) )function* func(){const ans yield test();console.log(ans);const ans2 yield test();console.log(ans2); }const it func(); const p it.next(); // 返回 {value: Promise,done: false }这是 ans 并没有获取到 resolve 的值 p.value.then(res {console.log(res);const p2 it.next(res); // 这一步时上面代码中的 ans 才会被确定值为 res;p2.value.then(res {console.log(res);}) })如果 next() 中不带参数则 yield 每次运行之后的返回值都是为 undefined即 yield 1 运行之后返回值为 undefined function * oddGenerator () {yield 1 // 值为 undefined } let iterator oddGenerator() let first iterator.next()应用场景 协程 协程可以理解成多线程间的协作比如说 AB 两个线程根据实际逻辑控制共同完成某个任务A 运行一段时间后暂缓执行交由 B 运行B 运行一段时间后再交回 A 运行直到运行任务完成。对于 JavaScript 单线程来说我们可以理解为函数间的协作由多个函数间相互配合完成某个任务Generator 函数是 ES6 对协程的实现但属于不完全实现。Generator 函数被称为“半协程”意思是只有 Generator 函数的调用者才能将程序的执行权还给 Generator 函数。如果是完全执行的协程任何函数都可以让暂停的协程继续执行如果将 Generator 函数当做协程完全可以将多个需要互相协作的任务写成 Generator 函数他们之间使用 yield 标识交换控制权Generator 函数执行产生的上下文环境一旦遇到 yield 命令就会暂时退出堆栈但是并不消失里面的所有变量和对象会冻结在当前状态。等到对它执行 next 命令时这个上下文环境又会重新加入调用栈冻结的变量和对象恢复执行。 异步编程 解决回调地狱异步流控按顺序控制异步操作例 普通方法实现肚包鸡的制作过程setTimeout(function() {console.log(prepare chicken);setTimeout(function() {console.log(fired chicken);setTimeout(function() {console.log(stewed chicken);....},500)},500) },500);用 Generator 函数来实现肚包鸡的制作过程// 准备 function prepare(sucess) {setTimeout(function() {console.log(prepare chicken);sucess();},500) }// 炒鸡 function fired(sucess) {setTimeout(function() {console.log(fired chicken);sucess();},500) }// 炖鸡 function stewed(sucess) {setTimeout(function() {console.log(stewed chicken);sucess();},500) }// 上料 function sdd(sucess) {setTimeout(function() {console.log(sdd chicken);sucess();},500) }// 上菜 function serve(sucess) {setTimeout(function() {console.log(serve chicken);sucess();},500) }// 流程控制 function run(fn) {const gen fn();function next() {// 返回工序函数的句柄给 resultconst result gen.next();if (result.done) return; // 结束// result.value 就是yield返回的值是各个工序的函数result.value(next); // value 就是制作过程中不同阶段的函数next 作为入参即本工序成功后执行下一工序}next(); };//工序 function* task(){yield prepare;yield fired;yield stewed;yield sdd;yield serve; }//开始执行 run(task);重点在流程控制部分很妙的思路 使用举例 实现自增 idfunction* next_id() {for (id 1; ; id) {yield id;} }实现 async 和 await 功能 await 实现const test (data) new Promise((resolve, reject) {setTimeout(() {resolve(data);}, 1000) })async function func(){const aaa await test(1)const bbb await test(2)return 3; }Generator 实现const test (data) new Promise((resolve, reject) {setTimeout((){resolve(data);}, 1000) })// 重点在这 function autoStart(generator) {const gen generator();return new Promise((resolve, reject) { // 最终应该返回一个 Promise 对象function _next(val) {const p gen.next(val);if(p.done) { // 递归结束条件console.log(p.value);resolve(p.value);return; //递归结束}// p.value 即 test() 返回的 Promise在 1000 毫秒后改变状态// 避免 p.value 为基本类型的情况不然应该是 p.value.then()Promise.resolve(p.value).then(res {// 在 Promise 改变状态的时候也就是 1000 毫秒后运行_next(res); // 本质就是递归})}_next();}) }function* generator(){const aaa yield test(1);console.log(aaa);const bbb yield test(2);console.log(bbb)return 3; }let res autoStart(generator);console.log(res); setTimeout(() {console.log(res); }, 5000);2. js 垃圾回收机制 为啥需要回收 在 js 中数据类型分为简单类型和引用类型简单类型内存是保存在栈空间中复杂数据类型内存是保存在堆空间中 基本类型这些类型在内存中分别占有固定大小的空间他们的值保存在栈空间通过按值来访问的引用类型引用类型值大小不固定栈内存中存放地址指向堆内存中的对象是按引用访问的 对于栈的内存空间只保存简单数据类型的内存由操作系统自动分配和自动释放 而堆空间中的内存由于大小不固定系统无法无法进行自动释放这个时候就需要JS引擎来手动的释放这些内存 js 两种 GC 机制 “引用计数” 早期的浏览器最常使用的垃圾回收方法语言引擎有一张引用表保存了内存里面所有的资源通常是各种值的引用次数。即数据存在堆内存中如果一个值的引用次数是 0就表示没有任何变量或数据指向它因此可以将这块内存释放被回收但这种方法对于 obj1.a obj2obj2.a obj1 这种互相指向的情况没有办法obj1 和 obj2 通过各自的属性相互引用所有它们的引用计数都不为零这样就不会被垃圾回收机制回收造成内存浪费所以现在已经废弃不用了引用计数算法其实还有一个比较大的缺点就是我们需要单独拿出一片空间去维护每个变量的引用计数这对于比较大的程序空间开销还是比较大的 “标记清除” 现在的浏览器最常使用的垃圾回收方法 核心思想分标记和清除两个阶段完成 遍历所有对象找标记活动对象遍历所有对象清除没有标记对象回收相应的空间 标记阶段 标记阶段就是找到可访问对象的一个过程对象的可达性垃圾回收是从一组对象的指针objects pointers开始的我们将其称之为根集root set这其中包括了执行栈和全局对象然后垃圾回收器会跟踪每一个指向 JavaScript 对象的指针并将对象标记为可访问的同时跟踪对象中每一个属性的指针并标记为可访问的这个过程会递归的进行直至所有节点没有可遍历的路径 清除阶段 标志阶段结束后未被打上标志的对象说明从根节点无法访问它垃圾回收器就会回收该内存 “标记清除算” 对比 “引用计数算法”标记清除法最大的优点是能够回收循环引用的对象它也是 v8 引擎使用最多的算法 但还是存在缺点空间碎片化 红色区域是一个根对象就是一个全局变量会被标记而蓝色区域就是没有被标记的对象会被回收机制回收。这时就会出现一个问题表面上蓝色区域被回收了三个空间但是这三个空间是不连续的当我们有一个需要三个空间的对象那么我们刚刚被回收的空间是不能被分配的这就是 “空间碎片化” GC垃圾回收的收集方法 标记清除 上面说的将未标记到的统一回收但会造成空间碎片化 标记整理 为了解决 “空间碎片化” 的问题提高对内存的利用标记整理可以看做是标记清除的增强标记阶段的操作和标记清除一致清除阶段会先执行整理移动对象位置,将存活的对象移动到一边然后再清理端边界外的内存但也还是存在缺点回收前需要移动对象位置不会立即回收对象回收的效率比较慢适合老年代进行垃圾收集     复制算法 也可以解决 “空间碎片化” 的问题提高对内存的利用它先将可用的内存按容量划分为大小相同的两块每次只是用其中的一块。当这块内存用完了就将还存活着的对象复制到另一块上面然后把已经使用过的内存空间一次清理掉牺牲空间换取时间所以缺点是将内存缩小位原来的一半适合新生代进行垃圾回收改进思路 由于新生代都是朝生夕死的所以不需要11划分内存空间可以将内存划分为一块较大的Eden和两块较小的Suvivor空间。每次使用Eden和其中一块Survivor。当回收的时候将Eden和Survivor中还活着的对象一次性地复制到另一块Survivor空间上最后清理掉Eden和刚才使用过的Suevivor空间。其中Eden和Suevivor的大小比例是81。缺点是需要老年代进行分配担保如果第二块的Survovor空间不够的时候需要对老年代进行垃圾回收然后存储新生代的对象这些新生代当然会直接进入来老年代 优化收集方法的思路分代收集算法 根据对象存活的周期的不同将内存划分为几块然后再选择合适的收集算法一般是分成新生代和老年代这样就可以根据各个年待的特点采用最适合的收集算法。在新生代中每次垃圾收集都会有大量的对象死去只有少量存活所以选用复制算法老年代因为对象存活率高没有额外空间对他进行分配担保所以一般采用标记整理或者标记清除算法进行回收 V8引擎的内存回收策略 分代内存 在V8引擎的内存结构中堆内存分为两类进行处理新生代内存和老生代内存 新生代内存是指临时分配内存存活时间短 【 新生代内存可分为两个区域 From-spaceTo-space 】 【 其中 from 区域还可细分为 nursery 子代和 intermediate 子代 】老生代内存是常驻内存存活时间长 【 新生区通常只支持 18M 的容量而老生区支持的容量就大很多了 】 垃圾回收器 对于这两块区域V8 分别使用两个不同的垃圾回收器以便更高效地实施垃圾回收 副垃圾回收器 - Scavenge复制算法主要负责新生代的垃圾回收主垃圾回收器 - Mark-Sweep Mark-Compact标记清除标记整理主要负责老生代的垃圾回收 晋升 如果新生代中的一个变量经过多次垃圾回收后依旧存活。该对象就会被认为是一个声明周期较长的对象被放入老生代内存中对象从新生代转移到老生代的过程称为晋升对象晋升的条件有两个 已经经历过一次 Scavenge即在Form空间中的 intermediate 子代区域中的对象To当前闲置空间内存占用超过25% 即在新生代中分为 nursery 子代和 intermediate 子代两个区域一个对象第一次分配内存时会被分配到新生代中的nursery子代如果进过下一次垃圾回收这个对象还存在新生代中这时候我们移动到 intermediate 子代再经过下一次垃圾回收如果这个对象还在新生代中副垃圾回收器会将该对象移动到老生代中这个移动的过程被称为晋升 采用分代收集算法 新生代采用 复制算法老生代采用 标记整理 或 标记清楚 算法 新生代中大部分对象在内存中存活的周期很短所以需要一个效率非常高的算法 老生代中对象都已经至少经历过一次或者多次的回收所以它们的存活概率会更大支持的容量交大会出现空间资源浪费问题 v8 解决全停顿问题 什么是全停顿 由于垃圾回收是在JS引擎中进行的而当活动对象较多的时候它的执行速度不可能很快为了避免JavaScript应用逻辑和垃圾回收器的内存资源竞争导致的不一致性问题垃圾回收器会将 JavaScript 应用暂停这个过程被称为全停顿在新生代中由于空间小存活对象较少Scavenge算法执行效率较快所以全停顿的影响并不大。而老生代中就不一样如果老生代中的活动对象较多垃圾回收器就会暂停主线程较长的时间使得页面变得卡顿orinocoV8的垃圾回收器 为了提升用户体验解决全停顿问题它利用了增量标记、懒性清理、并发、并行来降低主线程挂起的时间 增量标记优化标记过程 为了减少全停顿的时间V8 对标记进行了优化将一次停顿进行的标记过程分成了很多小步。每执行完一小步就让应用逻辑执行一会儿这样交替多次后完成标记长时间的 “全停顿” 垃圾回收用户体验感变得非常糟糕同时会严重影响性能从 2011 年起v8 就将「全暂停」标记换成了增量标记。改进后的标记方式最大停顿时间减少到原来的 1/6由于每个小的增量标价之间执行了 JavaScript 代码堆中的对象指针可能发生了变化需要使用写屏障技术来记录这些引用关系的变化所以也暴露出来增量标记的缺点 并没有减少主线程的总暂停的时间甚至会略微增加由于写屏障Write-barrier机制的成本增量标记可能会降低应用程序的吞吐量 懒性清理优化清理过程 当增量标记完成后假如当前的可用内存足以让我们快速的执行代码其实我们是没必要立即清理内存的可以将清理的过程延迟一下让 JavaScript 逻辑代码先执行也无需一次性清理完所有非活动对象内存垃圾回收器会按需逐一进行清理直到所有的页都清理完毕 并发式GC 并发式GC允许在在垃圾回收的同时不需要将主线程挂起两者可以同时进行只有在个别时候需要短暂停下来让垃圾回收器做一些特殊的操作。但是这种方式也要面对增量回收的问题就是在垃圾回收过程中由于JavaScript代码在执行堆中的对象的引用关系随时可能会变化所以也要进行写屏障操作 并行式GC 并行式GC允许主线程和辅助线程同时执行同样的GC工作这样可以让辅助线程来分担主线程的GC工作使得垃圾回收所耗费的时间等于总时间除以参与的线程数量加上一些同步开销 副垃圾回收器 V8在新生代垃圾回收中使用并行parallel机制在整理排序阶段也就是将活动对象从from-to复制到space-to的时候启用多个辅助线程并行的进行整理。由于多个线程竞争一个新生代的堆的内存资源可能出现有某个活动对象被多个线程进行复制操作的问题为了解决这个问题V8在第一个线程对活动对象进行复制并且复制完成后都必须去维护复制这个活动对象后的指针转发地址以便于其他协助线程可以找到该活动对象后可以判断该活动对象是否已被复制 主垃圾回收器 V8在老生代垃圾回收中如果堆中的内存大小超过某个阈值之后会启用并发Concurrent标记任务。每个辅助线程都会去追踪每个标记到的对象的指针以及对这个对象的引用而在JavaScript代码执行时候并发标记也在后台的辅助进程中进行当堆中的某个对象指针被JavaScript代码修改的时候写入屏障write barriers技术会在辅助线程在进行并发标记的时候进行追踪当并发标记完成或者动态分配的内存到达极限的时候主线程会执行最终的快速标记步骤这个时候主线程会挂起主线程会再一次的扫描根集以确保所有的对象都完成了标记由于辅助线程已经标记过活动对象主线程的本次扫描只是进行check操作确认完成之后某些辅助线程会进行清理内存操作某些辅助进程会进行内存整理操作由于都是并发的并不会影响主线程JavaScript代码的执行 V8 当前解决全停顿问题的方案 2011 年V8应用了增量标记机制。直至 2018 年Chrome64 和 Node.js V10 启动并发标记同时在并发的基础上添加并行技术使得垃圾回收时间大幅度缩短 3. 内存泄漏与优化 内存泄漏 内存泄漏指在 JS 中已经分配内存地址的对象由于长时间未进行内存释放或无法清除造成了长期占用内存使得内存资源浪费最终导致运行的应用响应速度变慢以及最终崩溃的情况 作用域分为全局作用域和局部作用域局部作用域分为函数作用域和块级作用域全局作用域的变量就是全局变量全局变量只有关闭页面才会回收局部变量在使用完毕后就会被回收比如一个函数里定义了一个变量在这个函数运行完毕后这个变量就会被回收 在代码中创建对象和变量时会占据内存但是 JS 基于自己的内存回收机制是可以确定哪些变量不再需要并将其进行清除。但是当你的代码中存在逻辑缺陷时你以为你已经不需要但是程序中还存在这引用这就导致程序运行完后并没有进行合适的回收所占有的内存空间。运行时间越长占用内存越多随之出现的问题就是性能不佳、高延迟、频繁崩溃 造成内存泄漏的常见原因及解决办法 原因过多的缓存 解决办法及时清理过多的缓存原因滥用闭包 解决办法尽量避免使用大量的闭包注意闭包对闭包进行限制不能无限制的增长例如当闭包里的数组进行 push 数据超过一定长度删除一些再继续push原因定时器或回调太多 解决办法与节点或数据相关联的计时器不再需要时DOM节点对象可以清除整个回调函数也不再需要。可是计时器回调函数仍然没有被回收计时器停止才会被回收原因当不需要setTimeout或setInterval时定时器没有被清除定时器的回调函数以及其内部依赖的变量都不能被回收会造成内存泄漏 解决办法在定时器完成工作时需要手动清除定时器。太多无效的DOM引用。DOM删除了但是节点的引用还在导致GC无法实现对其所占内存的回收 解决办法给删除的DOM节点引用设置为null。滥用全局变量。全局变量是根据定义无法被垃圾回收机制进行收集的因此需要特别注意临时存储和处理大量信息的全局变量。如果必须使用全局变量来存储数据请确保将其指定为null或在完成后重新分配它 解决办法尽量不要定义全局变量定义了也要及时手动回收如让这个变量的值等于 undefined、null 或重定义使用严格模式从外到内执行appendChild。此时即使调用removeChild也无法进行释放内存 解决办法从内到外appendChild。反复重写同一个数据会造成内存大量占用但是IE浏览器关闭后会被释放注意程序逻辑避免编写『死循环』之类的代码避免 DOM对象和 JS 对象相互引用 关于内存泄漏如果想要更好地排查以及提前避免问题的发生最好的解决方法是通过熟练使用 Chrome 的内存剖析工具多分析多定位 Chrome 帮你分析保留的内存快照来查看持续占用大量内存的对象 4. AST抽象语法树 AST 是什么 AST是源代码语法结构的一种抽象表示以树状的形式表现编程语言的语法结构树上每个节点都表示源代码中的一种结构 常见用途 编辑器的错误提示代码格式化代码高亮代码自动补全elint、pretiier 对代码错误或风格的检查webpack 通过 babel 转译 javascript 语法 AST 生成 代码执行的第一步是读取代码文件中的 字符流然后通过 词法分析 生成 token之后再通过 语法分析 生成 AST最后 生成 机器码执行。整个解析过程主要分为以下两个步骤 词法分析或叫分词将整个代码字符串分割成最小语法单元数组语法分析在分词基础上建立分析语法单元之间的关系 词法分析 词法分析也称之为 扫描 或者 令牌化Token这一步主要是将字符流char stream转换为令牌流token stream就是在源代码的基础上进行分词简单来说就是调用 next() 方法一个一个字母的来读取字符然后与定义好的 JavaScript 关键字符做比较生成对应的 tokentoken 是一个不可分割的最小单元词法分析器里每个关键字是一个 token 每个标识符是一个 token每个操作符是一个 token每个标点符号也都是一个 token。除此之外还会过滤掉源程序中的注释和空白字符换行符、空格、制表符等最终整个代码将被分割进一个 tokens 列表或者说一维数组例如词法分析器 从左往右逐个字符扫描分析 整个程序的字符串当遇到不同的字符时会驱使它迁移到不同的状态。在扫描字符的时候遇到 c 字母如果后面还有字符将继续扫描直到遇到空格识别出 const发现是一个关键字将其生成词法单元 { type: ‘Keyword’, value: ‘const’ }然后接着扫描以此类推生成 Token List 语法分析 语法分析会将词法分析出来的 token 转化成有语法含义的抽象语法树结构AST同时验证语法语法如果有错会抛出语法错误词法分析和语法分析不是完全独立的而是交错进行的也就是说词法分析器不会在读取所有的词法记号后再使用语法分析器来处理。通常情况下每取得一个词法记号就将其送入语法分析器进行分析 举例 使用的工具 AST explorer详情 function square(n) {return n * n; }经过转化输出 AST 结构如下 AST 的每一层都拥有相同的结构为了简化移除了某些属性 {type: FunctionDeclaration,id: {...},params: [...],body: {...} }{type: Identifier,name: ... }{type: BinaryExpression,operator: ...,left: {...},right: {...} }这样的每一层结构被称为 节点Node每一个节点都包含 type 属性用于表示节点类型比如FunctionDeclaration、Identifier、BinaryExpression 等等。除此之外Babel 还为每个节点额外生成了一些属性用于描述该节点在原始代码中的位置比如 start、end、loc 还有一些例子可以看出大概 AST 转换后的结构 while b ! 0 {if a ba a-belseb b-a } return asum0 for i in range(0,100)sumsumi endletteraddresscityShiChuang/city/addresspeopleid12478/idnameNosic/name/people /letter1 3 * ( 4 - 1 ) 25. babel 工作原理AST 的使用 具体的看这详情 节点类型babel AST 节点类型主要分为以下几个大类字面量、标志符、语句、声明、表达式、注释 等等 字面量Literal 标志符Identifier 程序中所有的 变量名、函数名、对象键key 以及函数中的参数名都属于标志符Identifier语句Statement 语句是能够独立执行的基本单位常见的语句类型有 声明Declaration 声明语句是一种特殊的语句它执行的逻辑是在作用域内声明一个 变量、函数、class、import、export 等 表达式Expression 表达式的特点是执行完以后有返回值这是和语句 (statement) 的区别 Comment Program babel 编译流程 babel 的编译过程和大多数其他语言的编译器大致相同可以分为 3 个阶段解析 → 转换 → 生成 解析Parser 将代码字符串解析成抽象语法树AST每个 JavaScript 引擎比如Chrome浏览器中的 V8 引擎都有自己的 AST 解析器而Babel是通过 babel/parser 实现的。解析过程有两个阶段词法分析 和 语法分析词法分析阶段把字符串形式的代码转换为令牌tokens流令牌类似于 AST 中节点而语法分析阶段则会把一个令牌流转换成 AST 的形式同时这个阶段会把令牌中的信息转换成 AST 的表述结构 转换Transform 对抽象语法树进行转换操作转换步骤接收 AST 并对其进行遍历在此过程中对节点进行添加、更新及移除等操作。 Babel 通过 babel/traverse 对其进行深度优先遍历维护 AST 树的整体状态并且可完成对其的替换删除或者增加节点这个方法的参数为原始 AST 和自定义的转换规则返回结果为转换后的 AST 生成Generator 根据变换后的抽象语法树再生成代码字符串同时还会创建 源码映射source maps代码生成其实很简单深度优先遍历整个 AST然后构建可以表示转换后代码的字符串Babel 通过 babel/generator 将 AST 转换成 js 代码过程就是深度优先遍历整个 AST然后构建可以表示转换后代码的字符串 babel apis 我们知道 Babel 的编译流程分为三步Parse → Transform → Generate每一步都暴露了一些 Api 出来 解析阶段通过 babel/parser 将源码转成 AST转换阶段通过 babel/traverse 遍历AST并调用 visitor 函数修改 AST期间涉及到 AST 的判断、创建、修改等这时候就需要 babel/types 了当需要批量创建 AST 的时候可以使用 babel/template 来简化 AST 创建逻辑生成阶段通过 babel/generate 将 AST 输出为目标代码字符串同时生成 sourcemap中途遇到错误想打印代码位置的时候使用 babel/code-frame 包Babel 的整体功能通过 babel/core 提供基于上面的包完成 Babel 整体的编译流程并实现插件功能 AST 实战babel AST 实战
http://www.w-s-a.com/news/662986/

相关文章:

  • 网站建设费大概多少钱成都网站建设低价
  • 做表格的网站东莞常平房价
  • 国家级建设网站高密做网站哪家强价位
  • 江西省新的建设厅三类人员网站做标记网站
  • 做最精彩绳艺网站产品设计培训
  • 营销型网站建设品牌深圳网络推广最新招聘
  • 单位网站等级保护必须做吗广州app软件开发公司
  • 免费flash网站模板怎么仿网站链接
  • 泉州网站建设哪家好平面设计转行做什么比较好
  • 忘记网站备案账号设计一个网站
  • 国内购物网站哪个最好海珠营销网站建设报价
  • 小型网站搭建logo免费制作
  • dede 网站模板哈尔滨房产信息网官方网站
  • 设计师个人作品集模板班级优化大师网页版登录
  • 高端网站建设教学网站开发前期准备工作
  • 网站评论列表模板设计官网的
  • 怎么做可以访问网站ui设计自学学的出来吗
  • 网站如何接入支付宝软件开发工作内容描述
  • 廊坊网站建设搭建整合营销传播的效果表现为
  • 网站服务器在本地是指园林绿化
  • 公司网站建设需要什么科目网站代运营价格
  • 网站建设前的ER图ppt模板图片 背景
  • 做一个网站花多少钱网站导航营销步骤
  • 仙桃网站定制做房产网站能赚钱吗
  • 西安网站制作模板最新源码
  • 南京江宁网站建设大学高校网站建设栏目
  • 模板网站建设明细报价表做网站第一
  • 公司网站建设系统软件开发 上海
  • 怎么让公司建设网站固安县建设局网站
  • 360免费建站官网入口手机网站建设设计