ECMAScript版本介绍
ECMAScript 是什么
- 这套规范是由 sun 和 netspace共同提出的以ECMA-262为标准和基础的一套javascript 语言规范。
- 这是JavaScript基本语法规则的规范,其中定义了,语法,关键字,保留字。
ECMAScript 发展史
- 1998 年 ECMAScript 2.0 发布
- 1999 年 ECMAScript 3.0 发布
- 2007 年 提出了 ECMAScript 4.0 因为太激进被各大浏览器厂商及互联网公司联合抵制,最终没有发布。
- 2008 年 放弃4.0计划,改为3.1优化计划,只做了小部分更新,我们现在写的最早的版本大概就是 3.1 版本了。
- 2009 年 发布了ES5
- 2011 年 修正了ES5 发布了 ES5.1 这个标准是目前国标版本,也就是说所有的2011年之后的浏览器必须支持的版本。
- 2015 年 经过 2013 年多次波折和延期发布,终于发布了ES6 版本。
- 因为ES6版本发生了加大的变更,同时太多的想法也在慢慢计划和实施,所以ECMAScript 从2015年起, 每年都会更新一版。
- ES2015 以后的版本我们通常称之为ES6 +
版本迭代的那些事
其实版本的迭代,无外乎让自己变得更优秀,一个语言如果想要变得更优秀,那么其实有两条路可以走。 一条路是变得尽可能强大,尽可能可靠像是 c ++ 和 java 。 另外一个是尽可能降低学习成本, 让你几乎无所不能 的同时可以肆无忌惮的发挥自己的想象,做的最好的当然就是JavaScript。
- 老话说的好,不积跬步无以至千里,不积小流,无以成江海。
- 虽然自打 ES2015 以来,每年的 ECMAScript 更新都不会太多,但是我们还是要时刻学习时刻进步,让我们的语法理解永远领先浏览器。
- 站的更高才能看得更远。
- 闲话就不叙了,看下正文内容
ECMAScript版本的更新无外乎围绕这以下几方面展开
解决低性能封装
- 因为javascript语言本身的特性导致JavaScript编程的自由度非常高(其实就是语言本身的规定较少),所以很多的封装并不成熟
- 为了提高开发人员工作效率,在新的JS版本之中提供了非常多新的API
- 如 ES5 版本的
forEach
,indexOf
, ES6 + 的padStart
,falt
等非常多的API
降低开发人员入门门槛
- JavaScript本身在设计的时候没有考虑到很多的功能,导致很多可以极大提升开发效率的API,在编程初期因为语言本身没有提供,自己也没有足够的能力封装,这样很多强大的API没法使用。
- 比如 jQuery 的
$.Deferred
对象是用来解决回调地狱问题的, 现在有了Promise
,就不必引入 庞大的jQuery库或者自己封装了。 - 再比如 jQuery 里面的对象合并功能
$.extend
也被替换成了Object.assign
- 类似的API有非常多 , 总而言之新版本降低了开发人员的入门门槛。
修正语言在设计之初没有考虑的问题
- 比如ES5之中提供的严格模式,提高代码的执行效率, 减少了很多乌龙代码,降低了代码的维护成本。
- ES6之中新增的块级作用域,让JS不用每次使用作用域都需要用到函数。
干掉了JS之中某些非常恶心的写法
- 比如async , await , class这样的关键字,解决了非常之难写的回调函数。提供了非常香甜的语法糖。
提供了以前不支持的新东西
- 常量,新的数据结构 , Set, Map, 这个不用担心在ES6之后就基本已经补齐了开发所需,几乎追平了主流语言,所以对我们来说这种新东西学一个少一个 。
- 某些新的可以使用的特性 , 比如在 class 之中添加了
#
还有static
这类的新东西 - 再比如说新增的各种运算符
**
,?.
,??
..
来自ECMAScript的深情告白 : 其实所有语言版本的更新都是为了让我们更快速,更有效率的完成我们的开发工作,JavaScript这个语言像是穷苦出身的孩子,天赋一般,成绩一般,但是在自己不屑的努力下,终于在这个时代占据了属于自己的重要一席,因为JavaScript的每一次改变都是为了更好的自己和更方便使用它的你。
- 一句话: 新东西来了,学就完了。
ES2020版本的新特性
提供了新的API :
Promise的allSettled
原本的Promise.all 在某一个程序报错后,会终止其余程序执行,但是allSettled不会终止其程序执行, 属于一个优化版的Promise.all。
正则的matchAll
-
原本的match方法分成两种返回形式 :
- 匹配到的数据只有一个 , 以对象的形式返回详情 :
{ input : xxx , xxxx.}
- 匹配到的数据只有一个 , 以对象的形式返回详情 :
- 匹配到的数据有多个 , 以数组的形式返回所有匹配到的数据。
现在的matchAll 可以匹配所有的项并以详情的形式返回 一个数组对象。
globalThis
因为 web端的全局对象是 window, nodejs的全局对象是global , 为了统一两者的使用,所以es2020 建立了新的关键字 globalThis。
这个关键字实现了window===globalThis
还有global===globalThis
。
新的语法规则,修正了之前的不足
运算符类 :
- 可选链式调用 : 其实就是对
.
取出运算的优化 ,避免的取出运算的报错。
// 我们声明一个对象
var obj = { a : 10 }
// 如果使用正常的取出运算符 , 在取出为undefined或者null的时候,JavaScript会给我们报出一个类型错误
// 例如 :
obj.c.a
// 这个连续运算就会报出类型错误 : TypeError : Cannot read property 'a' of undefined
// 因为 obj.c 运算那结果为 undefined
// undefined.a 就出现了配合undefined的取出运算。
- 因为JavaScript是单线程的原因,所有在报错的时候,会导致代码终止执行,为了避免类似的报错出现,让我们可以用更优雅从容的方式解决错误逻辑,ES2020给我们提供了可选链式调用运算
?.
- 具体使用
var obj = { a : 10 }
obj.c?.a
// 这个运算第一步obj.c 还是 undefined
//所以第二步的运算是 undefined?.a
// 这个运算符,在进行取出的时候,会判定前面的值是否为 undefined 或者 null 如果是,那么则返回undefine ,不会报错。
//我们在使用对象的时候可以规避开报错。
这种运算,不建议在开发阶段使用, 因为这可能导致无法正常排查错误。
建议在项目上线后在敏感区域替换,确保在字段查询为空的情况下,或者数据返回错误的情况下程序可以正常运行。
空值合并
我们在处理默认参数的情况下都是用
||
运算,利用其短路特性进行处理。我们来看一下短路运算在设置默认参数的时候会发生什么问题
// 如果我们想要给函数的参数设置默认值,那么我们就可以使用这样的方式。
function foo( option ){
option = option || "hello world"
}
// 这个运算的涵义很简单,如果option 传入的参数经过转换为true,那么则直接返回option , 不会继续运算。
// 如果传入的参数转换为false,那么我们就把option设置为默认值"hello world"
- 根据JavaScript数据类型的转换规则,我们应该了解, 如果我们传入的实参为
""
,0
,false
,null
则无法正常赋值为传入的参数,因为这些类型都会被转换为 false, 直接触发||
运算的短路。 - 在 ES2020 中我们可以把
||
运算替换成??
运算,实现空值的合并,这个合并可以兼容 数字0
。 - 注意 : 这个合并是不能同时兼容
undfeind
类型和null
类型的
function foo( option ){
option = option ?? "hello worold"
}
- 这样则可以让option的默认值为任意值。
class类 :
class 静态字段
其实class这个东西一直都存在一定的不足,因为在ES6增加了
class
关键字之后,确实没有提供static
这样的方法, 那么很多类的触发器就要内置, 会导致一些尴尬的问题。
class Foo{
init(){
// 触发功能;
}
}
- 这个
Foo
类在其他位置需要使用的时候,我们需要两个步骤,第一个步骤先去let foo
, 第二个步骤let foo = new Foo()
实例我们当前的构造函数。 - 多了一个全局变量, 为了最大程度的节省全局命名空间,
class
给我们提供了static
字段 - 这个字段可以让我们在任意位置访问类之中的内容。
class Foo{
static init(){
// 触发调用当前类
}
}
在这里我们使用
init
功能只需要Foo.init()
即可。class 私有字段
如果涉及到命名空间可能的冲突,在自己的类内部定义一下方法可以使用,私有字段。
定义的方式是 :
#名称=值
class Foo{
#hello="hello world";
init(){
console.log(this.#hello) // hello world
}
}
let foo = new Foo();
foo.init();
console.log(foo.#hello)// 报错 ;
语法规则类
- 顶级await
- 在之前的版本上我们使用
await
关键字需要在async
定义的函数之中使用,所以我们在页面初始情况下需要加载数据的话,就要使用匿名函数,变成如下形式 :
(async ()=>{
await res = fetch("xxx");
})()
- 那么在ES2020支持了顶级await之后,我们的代码就少了这种无用的包裹,更加简洁的实现了数据的加载,我们甚至可以在代码执行之前,定义必要的依赖引入
await res = fetch("xxx");
在JS解析规则上来讲, 后面的内容都会放在回调函数里,所以,如果我们需要优先加载数据完全可以使用这样的全局await对数据进行加载,急剧的简化了我们的开发成本。
动态引入
这个语法规则, 之前是仅在webpack之中支持的,ES2020 在原生的解析器之中支持了这种写法 , 其意义也是相当于在web端支持了 COMMONJS 的同步
require
方式。具体语法如下 :
import (xxxx).then(function(res){
console.log(res);
})
参数之中的错误抛出
很遗憾没法测试,因为截止目前为止我们的浏览器不支持这种最新的语法。
但是他可以让我们自定义跟多的错误,至少算是少些了一个逻辑。
let foo = ( arg = throw new TypeError("参数类型错误"))=>{
}
try catch
这个用法单纯的就是对原版本
try catch
学习成本的降低。在ES2020之中我们的
try catch
可以不在catch之中传递参数了。
try {
return JSON.parse(await readFile(optionalConfigFilePath))
} catch {
return {}
}
- 如果你对本文感兴趣 , 或者想要获得更多的课程资料可以添加QQ : 931673916 , 或者email : 931673916@qq.com
-
最后附上学习脑图 :
ES2020.mindmap.png