什么是JavaScript
JavaScript是一种脚本语言,1995年时,由Netscape公司在网景导航者浏览器上实现。浏览器内置JavaScript引擎来解释执行,用来给网页增加动态功能。Netscape希望它看起来像Java,因此取名为JavaScript,实际上毫无共通之处。Java和JavaScript的关系,就好比“老婆”和“老婆饼”的关系。
什么是ECMAScript
由于微软等公司也推出浏览器上运行的脚本语言进行竞争,1996 年Netscape 公司决定将 JavaScript 提交给标准化组织 ECMA(“European Computer Manufacturers Association”,欧洲计算机制造商协会),希望这种语言能够成为国际标准。次年,ECMA 基于JavaScript发布ECMA-262标准文件第一版,即ECMAScript 1.0 。为体现开放性和中立性,并避免侵犯Sun公司的商标权,该标准被称为ECMAScript而非JavaScript。
ECMAScript 和 JavaScript 的关系
ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的实现之一。通常下这两个词是可以互换。
ECMAScript 1.0 是 1997 年发布的,接下来的两年,连续发布了 ECMAScript 2.0(1998 年 6 月)和 ECMAScript 3.0(1999 年 12 月)。3.0 版在业界得到广泛支持,成为通行标准,奠定了 JavaScript 语言的基本语法并得到完全继承。今天学习 JavaScript,其实就是在学 3.0 版的语法。
什么是ES5
2009 年 12 月,ECMAScript 5.0 版(ES5)正式发布,2011 年 6 月,ECMAScript 5.1 版发布,并且成为 ISO 国际标准(ISO/IEC 16262:2011)。ES5 与 ES3 基本保持兼容。
什么是ES6
ES6即ECMAScript 6.0,是 2015 年 6 月正式发布JavaScript 语言标准,是继ES5之后的一次主要改进,增添了许多必要的特性,例如:模块和类,并且完全兼容以前的版本。目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。
参考: https://es6.ruanyifeng.com
ES6 与 ECMAScript 2015 的关系
ES6 和 ES2015 实际上是同一个东西。 由于技术委员会规定ECMAScript 必须做到每年做一次更新。由此,这个版本被更名为 ES 2015,此后新版本(从 2015 年起) ES 命名也都是是根据年份来算的: ES2015、 ES2016、 ES2017... 目前最新的草稿已经到了ES2021( https://tc39.es/ecma262/ )
什么是Node.js
最初JavaScript只能运行于客户端的浏览器,依赖于浏览器上的引擎。2009年5月,Ryan Dahl发布了Node.js平台,对谷歌的Chrome V8引擎进行了封装,从而使JavaScript可以脱离浏览器,独立运行于服务端。
实质是:Node.js 是 JavaScript 的服务器运行环境(runtime),并且它对 ES6 的支持度很高。
什么是模块化
模块化是指把一个复杂的系统分解到一个一个的模块
模块化开发的优点:
(1)代码复用,让我们更方便地进行代码管理、同时也便于后面代码的修改和维护。
(2)一个单独的文件就是一个模块,是一个单独的作用域,只向外暴露特定的变量和函数。这样可以避免污染全局变量,减少变量命名冲突。
早期的JavaScript缺乏对模块化的支持,后来发展出来的js模块化规范有:CommonJS、AMD、CMD、ES6的模块系统。
参考来源:https://zhuanlan.zhihu.com/p/53125734
什么是CommonJS模块化
服务器端模块的规范,由Node.js推广使用。该规范的核心思想是:允许模块通过require方法来同步加载所要依赖的其他模块,然后通过 exports 或module.exports 来导出需要暴露的接口。
实例:
可以这样加载:
实际上,从上面的例子就可以看出,math.add(1,2)必须要等待math.js加载完成,即require是同步的。
什么是AMD模块化
AMD:异步模块定义。上面已经介绍过,CommonJS是服务器端模块的规范,主要是为了JS在后端的表现制定的,不太适合前端。而AMD就是要为前端JS的表现制定规范。由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是require.js(还有个js库:curl.js)。实际上AMD 是 require.js在推广过程中对模块定义的规范化的产出。
math.js定义一个模块:
导入和使用:
math.add()与加载math模块不是同步的,不会阻塞浏览器的加载。
什么是CMD模块化
CMD:通用模块定义。
国内的玉伯大佬写了sea.js,实际上CMD就是 sea.js在推广过程中对模块定义的规范化的产出。
说明:
require:可以把其他模块导入进来的一个参数;
exports:可以把模块内的一些属性和方法导出的;
module: 是一个对象,上面存储了与当前模块相关联的一些属性和方法。
上面示例中的代码改写成CMD形式:
CMD与AMD的不同的在于:
(1)AMD推崇依赖前置;CMD推崇依赖就近,只有在用到某个模块的时候再去require:
(2)AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。
对于依赖的模块,AMD是提前执行,CMD是延迟执行。
具体细节可点击 参考
什么是ES5的模块化
其实就是指CommonJS(服务器端)和AMD(浏览器端,require.js)
CommonJS模块化和AMD模块化的区别
CommonJS服务器端,AMD浏览器端。
什么是ES6模块化
在ES6标准出来之前,大家都是commonJS或者AMD规范来模块化。ES6在语言的层面上实现了模块化。浏览器厂商和 Node.js 都宣布要原生支持该规范。它将逐渐取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
在 ES6 中,使用export关键字来导出模块,使用import关键字引用模块。但是浏览器还没有完全兼容,需要使用babel转换成ES5。
示例中的代码改写成ES6形式:
缺点
浏览器还没有完全兼容,必须通过工具转换成标准的 ES5 后才能正常运行。
为什么需要Babel和Webpack
ES6引入了模块化后,不同功能的代码可以分开写成module的形式。
但目前的浏览器环境,并不支持ES6 module写法, 所以我们需要借助webpack打包工具和babel转码器来生成可运行的代码。
什么是Babel 转码器
Babel 是 ES6 转码器或者说编译器,将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持...吗?
什么是Webpack
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
Webpack和Babel什么关系
参考来源:https://www.jianshu.com/p/c8b27e40d433
Webpack是打包工具,Bable是转码器,两者一起使用。我们只需要配置入口js文件,webpack会自动解析模块间的依赖关系,
通过babal-loader调用babel去转译相应的模块,最后打包成一个目标js文件。
有了Babel为什么还需要Webpack
babel承担了“翻译”的角色,把es6的写法转换成es5的写法。
但是有些人可能在一个项目中单独安装完babel,并成功生成了新的文件后,发现导入这个文件到浏览器中却报错了。其中很有可能被误导的是 import这个关键词。
实际上babel转换后的代码是遵循commonJS规范的,而这个规范,浏览器并不能识别。因此导入到浏览器中会报错,而nodeJS是commonJS的实现者,所以在babel转换后的代码是可以在node中运行的。
为了将babel生成的commonJS规范的es5写法能够在浏览器上直接运行,我们就借住了webpack这个打包工具来完成,因为webpack本身也是遵循commonJS这个规范的,从它的配置文件webpack.config.js中就可以看出来。
Webpack的工作方式
参考来源:https://www.jianshu.com/p/42e11515c10f
把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
Babel的局限性
即便使用了 Babel ,也做不到放心大胆的使用ES6,否则会被各种 undefined 的报错无情打脸。
上面这样的代码交给 babel 编译时,我们得到了:
可以看到,Babel只能进行语法转换,arrow function 被编译成了普通的函数形式,完美。
但是Object.assign作为 es2015 的新方法,没有可以被自动转换为的老函数。
一句话概括, babel 的编译不会做 polyfill。那么 polyfill 是指什么呢?
什么是Polyfill
Polyfill如何实现
1,分别引入替换插件babel-plugin-transform-xxx,比如替换Object.assign的babel-plugin-transform-object-assign
2,babel 提供了 babel-plugin-transform-runtime,从一个统一的地方 core-js 自动引入对应的方法
3,babel 直接提供了通过改变全局来兼容 es2015 所有方法的 babel-polyfill
三种方式各有优缺点和适用场景,而且使用不当会造成很难以发现的问题。参考:21 分钟精通前端 Polyfill 方案
4,babel-preset-env 支持针对指定目标环境选择需要的 polyfill 了,只需引入 babel-polyfill,并在 babelrc 中声明 useBuiltIns,babel 会将引入的 babel-polyfill 自动替换为所需的 polyfill。
5,polyfill.io 服务器会判断浏览器 UA 返回不同的 polyfill 文件,你所要做的仅仅是在页面上引入这个文件,polyfill 这件事就自动以最优雅的方式解决了。更加让人喜悦的是,polyfill.io 不旦提供了 cdn 的服务,也开源了自己的实现方案 polyfill-service。简单配置一下,便可拥有自己的 polyfill service 了。
上面两种方式也有缺陷,参考:21 分钟精通前端 Polyfill 方案 坑这么多,真替前端技术人员捂脸。
什么是npm
npm的出现,是为了解决前端开发中的代码复用问题,让全世界的前端开发人员可以互相分享并复用所有人的代码。
参考来源:https://www.jianshu.com/p/c36666b306aa
【node package management】,是nodejs内置的软件包管理器。毫无疑问,npm是用来管理软件包的。
什么是yarn
yarn的出现,是为了解决npm的问题
参考来源:https://www.cnblogs.com/wendyw/p/11494036.html
Yarn:Yet Another Resource Negotiator,是一个快速、可靠、安全的依赖管理工具,一款新的JavaScript包管理工具。可以替代npm。
未完(写不下去了... 向勇于攀登的前端技术同学致敬)