Code Monkey home page Code Monkey logo

blog's Introduction

Hi there, I'm GaoXiang

Now I'm working at HongSong Entrepreneurial team as a web frontend developer.

Blog:link / zhihu:link / bilibili:link /

Languages and Tools:

blog's People

Contributors

gaoxianglyx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

blog's Issues

ES6模块解析,对比CommonJS

ES6模块

ES6模块的特点

  1. 总是处于严格模式
  2. 具有顶层 (top-level) 作用域,但又不是全局 (global) 作用域(import命令具有提升效果,不管写在哪一行都会提到模块头部首先执行)
  3. 可以通过 import 关键字从其他模块导入程序绑定 (bindings, 通常就是变量或者函数)
  4. 可以通过 export 关键字导出指定的 bingdings

严格模式(以下会报错)

  • with 语句
  • 函数重复命名的参数
  • 八进制数字直接量 (比如 010)
  • 重复属性名 ( ES5 会报错,ES6 不会)
  • 使用 implements, interface, let, package, private, protected, public, static 和 yield 作为标识符

ES6的模块的静态加载

  • 静态加载:在编译阶段进行加载(预编译)

JS是脚本语言,是边执行边编译的,这里的编译阶段应该是指的执行前的这个编译解释阶段

  • 动态加载:在运行时加载依赖

ES6模块的设计**,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。commonjs和AMD模块,都只能在运行时确定这些东西。

  • 运行时加载: CommonJS/AMD 模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”
  • 编译时加载: ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,输入时采用静态命令的形式。即在输入时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载

Commonjs和ES6模块的运行机制就像是深复制和浅复制

ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,ES6模块是动态引用。

  • 在 CommonJS 中,导入(imports)是模块导出值的复制值(同时 require()动作是同步的)。也就是说,在一个模块中一个值和这个值导出被复制后的值不是同一个,两者之间不存在连接
  • 在 ES6 中,导入是对导出值的只读。因此,模块中的值和导出后的值是同一个,存在连接,只是在导入的模块中对这个值是只读的。“只读”说明在导入的模块中不能直接修改被导入的值,如果要修改被导入的值,可以通过调用被导入模块的函数来达到目的。

静态模块结构的优势:

  1. 在打包时消除死代码(dead code)。在项目开发的过程中,我们可以借助 ES6 实现模块化开发;在部署的时候,可以把这些分散的模块集中打包集成(打包减少了网络请求的数量,这点并不时很关键,因为在 HTTP/2 中将会有所改变;打包压缩了代码,减少了代码的体积;在打包过程中,没有用到的代码将会被移除)。
  2. 简洁高效的打包,不存在定制的打包格式(compact bundling, no custom bundle format)。ES6 模块可以被高效地合并,是因为所有的模块都被当作一个单独的作用域(single scope)(通过重命名变量来消除名冲突)。这些得益于 ES6 模块的两个特性:
  • 静态模块结构不存在模块的条件加载(但是仍可以通过把模块放到函数中来实现);
  • 导入对到导出的值只读,这意味着我们无需复制导出的值,而直接访问导出的值。
  1. 更快的导入检索(faster lookup of imports):
  • 在 CommonJS 中,通过复制来导入,同时模块存在动态机制(导出、导入),因而在查找属性的时候更加慢;
  • ES6 模块时静态的,意味着在模块执行之前就已经知道导入的值是什么,可以优化访问。
  1. 变量检查。同样得益于 ES6 的静态模块结构,我们可以在执行前进行导入、导出的变量检查。
  2. 为宏指令做准备(ready for macros)。macros 会是 JavaScript 发展蓝图中的一个 milestone。目前可以通过一些第三方的库来实现宏定义。
  3. 静态类型(static types)定义.
  4. 静态结构为支持其他编译型语言提供了可能。

模块化-AMD规范———— ESL

AMD规范
AMD 适合浏览器环境开发的主要特性有下面几点:

  • 开发时不需要页面上写一大堆 script 引用,一个 require 初始化模块就搞定。不需要每增加一个文件,就需要到 HTML 或者其他地方添加一个 script 标签或文件声明。
  • 开发时不需要依赖额外的环境,如果不是联调或数据模拟,直接 file:// 都能跑。。
  • 方便打包构建,打包构建应该便于进行模块的合并,并且在绝大多数场景不需要对页面进行修改。
  • 能够通过多种构建方案产生多种打包组合,方便从系统加载过程与缓存进行性能优化。特别是规模较大的应用,哪些东西首次加载、哪些东西缓加载、哪些东西需要被拼合、哪些东西经常变更等等,在构建的时候都会被考虑,对系统性能都可能有较大的影响。

AMD define的形式

define(id?, dependencies?, factory);
id - string
dependencies - Array
factory - Function | Object

AMD使用

  • 将模块 ID 交给应用页面决定,便于重构和模块迁移。模块开发者应该适应这点,从模块定义时就决定模块名称的思路中解放出来。这是使用 AMD 的开发者能获得的最大便利
  • 模块划分应尽可能细粒度,细粒度划分模块,有助于更精细地进行模块变更、依赖、按需加载和引用等方面的管理,有利于让系统结构更清晰,让设计上的问题提早暴露,也能从一定程度上避免一些看起来也合理的循环依赖。
  • 在 factory 中使用 require 引用依赖模块,不要写 dependencies 参数,没必要回到头部,也可以避免依赖循环
  • 即用即记载,require 与使用的距离越远,代码的阅读与维护成本越高。
  • 避免无意义的 装载时依赖。
  • 遵守 即用即 require 可以有效避免出现死循环依赖。
  • 模块的资源引用,在 factory 头部声明,如css资源什么的,会比较清晰

AMD初始化

  • AMD 对于下面两种情况,无法保证初始化顺序
    • factory 内部 require 的依赖模块
    • 在 dependencies 中声明但是在 factory 形参列表之外的依赖模块
  • CMD采用用时定义,确实可以保证模块初始化定顺序=声明顺序
  • 其实 requireJS也可以不提前写好依赖(像cmd一样),最主要的是require无法保证完全按顺序加载
  • 对于两种加载的方式,AMD规范并没有明确限制,requireJS提供了前置依赖和用时依赖两种书写方式,不过都是在factory执行前就把依赖给加载并执行;CMD是你requrie某个依赖的模块时候,才开始执行这个依赖模块的factory(Execution must be lazy);
  • esl对于两种情况采用不同的加载方式,融合了require和sea,明确了分别的处理方式,没有限制只有一种初始化方式,所以依然属于amd规范
  • PS:在正式的项目里面,确实考虑得很多,感觉自己现在仅仅是理解这些已经有点疲倦了。怎么让自己快速接受这种**呢?专注得进入这种状态吧

使用ESL

  • esl主要解决requireJS的痛点——体积太大
  • ESL完全解决了依赖循环的问题
  • 性能比requireJS强
  • 对于多次normalize进行缓存

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.