正文
Part1 · JavaScript【深度剖析】
ES 新特性与 TypeScript、JS 性能优化
文章说明:本专栏内容为本人参加【拉钩大前端高新训练营】的学习笔记以及思考总结,学徒之心,仅为分享。如若有误,请在评论区支出,如果您觉得专栏内容还不错,请点赞、关注、评论。
共同进步!
上一篇:【JavaScript异步编程】、【手写promise】
一、ECMAScript概述
ECMAScript,即 ECMA-262 定义的语言,并不局限于 Web 浏览器。事实上,这门语言没有输入和输出之类的方法。ECMA-262 将这门语言作为一个基准来定义,以便在它之上再构建更稳健的脚本语言。
Web 浏览器只是 ECMAScript 实现可能存在的一种宿主环境(host environment)。宿主环境提供ECMAScript 的基准实现和与环境自身交互必需的扩展。扩展(比如 DOM)使用 ECMAScript 核心类型和语法,提供特定于环境的额外功能。其他宿主环境还有服务器端 JavaScript 平台 Node.js 和即将被淘汰的 Adobe Flash。
日常使用的Web环境下,JavaScript语言包括:ECMAScript、浏览器提供的BOM对象、DOM树。
Node.js环境下,JavaScript包括:ECMAScript、Node API(fs、net、etc.)
历史版本:
二、ES2015概述
ECMA-262 阐述了什么是 ECMAScript 符合性。要成为 ECMAScript 实现,必须满足下列条件:
此外,符合性实现还可以满足下列要求。
以上条件为实现开发者基于 ECMAScript 开发语言提供了极大的权限和灵活度,也是其广受欢迎的原因之一。
三、ES2015 let 与块级作用域
具体详情请阅读《JavaScript高级程序设计·第四版》中的第三章第三节(3.3)
1.var
var定义的变量会预解析,简单的说就是如果变量没有定义就直接使用的话,JavaScript回去解析这个变量,代码不会报错,只会输出undefined。
console. log ( foo)
var foo = 'foo' ;
var定义的变量可以反复去定义,当然后面的会覆盖前面的
var a = 1 ;
var b = 2 ;
for ( var i = 0 ; i < 3 ; i++ ) {
for ( var i = 0 ; i < 3 ; i++ ) {
console. log ( i)
}
console. log ( '内层结束 i = ' + i)
}
在循环绑定事件过程中,var定义的变量无法保存,循环会在瞬间执行完
var elements = [ { } , { } , { } ]
for ( var i = 0 ; i < elements. length; i++ ) {
elements[ i] . onclick = ( function ( i) {
return
} )
}
elements[ 1 ] . onclick ( )
2.let
let定义的变量不会预解析,必须先声明再使用,否则会报错
console. log ( b) ;
let b = 'bar'
let不能定义已经定义过的变量(无论之前是用var定义的还是let或者const定义的)
let b = 3 ;
let c = 4 ;
let是块级作用域,函数内部使用let定义后,对函数外部无影响,简单说就是在一个{}里面生效
for ( let i = 0 ; i < 3 ; i++ ) {
let i = 'foo' ;
console. log ( i)
}
由于let是块级作用域,在循环绑定事件过程中let会在这个循环中生效,再次循环时let会重新定义生效
let elements = [ { } , { } , { } ]
for ( let i = 0 ; i < elements. length; i++ ) {
elements[ i] . onclick = ( function ( i) {
console. log ( i)
} )
}
elements[ 0 ] . onclick ( )
四、ES2015 const
const定义的变量不会预解析,必须先声明再使用,否则会报错
console. log ( a) ;
const a = 'foo' ;
const定义的变量不允许修改
const a = 5 ;
a = 6 ;
但是,在数组里面,const的值是允许被修改的,这是因为const存储的是地址,值的内容可以变化
const arr = [ 1 , 2 , 3 , 4 , 5 ]
arr[ 1 ] = 'array'
console. log ( arr) ;
五、ES2015 数组的解构
ECMAScript2015 新增了一种从数组或者对象获取指定元素的快捷方式,这是一种新的语法,这种新语法叫做
解构
。如下代码所示,定义一个数组:
const arr = [ 100 , 200 , 300 ]
const foo = arr[ 0 ]
const bar = arr[ 1 ]
const baz = arr[ 2 ]
console. log ( foo, bar, baz)
在 ECMAScript2015 之前想要获取这个数组中的元素,需要通过索引访问对应的值,然后将访问的结果赋值给一个变量。
而在 ECMAScript2015 之后,可以通过数组的解构这种方式快速获取数组中的指定成员。如下代码所示:
const arr = [ 100 , 200 , 300 ]
const [ foo, bar, baz] = arr
console. log ( foo, bar, baz)
这里会根据变量的位置进行分配数组中对应位置的成员。如果只要获取某一个位置上的成员,比如上个数组中的最后一个位置的成员,只需要保留前两个占位就可以了。如下代码所示:
const arr = [ 100 , 200 , 300 ]
const [ , , baz] = arr
console. log ( baz)
除此之外,还可以在变量名前面增加
...
来获取从当前位置到数组最后的所有成员。如下代码所示:
const arr = [ 100 , 200 , 300 ]
const [ foo, ... rest] = arr
console. log ( rest)
这里需要注意的是
,这种解构的用法只能在成员变量的最后一个变量上才能使用。
如果解构的变量数量少于数组的成员数量的话,那会按照从前到后的顺序进行获取。如下代码所示:
const arr = [ 100 , 200 , 300 ]
const [ foo] = arr
console. log ( foo)
从打印的结果可以看到,数组中剩下的成员都不会被获取到。反之,如果解构的变量数量多于数组的成员数量的话,那多出来的变量的值为
undefined
。如下代码所示:
const arr = [ 100 , 200 , 300 ]
const [ foo, bar, baz, more] = arr
console. log ( more)
使用 ECMAScript2015 之后的解构将大大进行简化。如下代码所示:
const path = 'foo/bar/baz'
const [ , rootDir] = path. split ( '/' )
console. log ( rootDir)
六、ES2015 对象的解构
在 ECMAScript2015 中,除了数组可以被解构之外,对象同样也可以被解构。只不过对象的解构,是需要通过属性名来获取,而不是位置。如下代码所示:
const obj = {
name: '拉勾大前端' ,
age: 3
}
const {
name
} = obj
console. log ( name)
上述代码的运行结果如下:
拉勾大前端
这里解构中的变量名还有一个很重要的作用,就是匹配解构对象中的成员,从而获取指定成员的值。比如上述代码结构总的
name
获取了
obj
对象中的
name
属性值。
因为对象的解构的这种特性,如果当前作用域中存在一个同名的变量,就会产生冲突。如下代码所示:
const obj = {
name: '拉勾大前端' ,
age: 3
}
const name = '拉勾大前端2'
const {
name
} = obj
console. log ( name)
上述代码的运行结果如下:
object-destructuring.js:13
name
^
SyntaxError: Identifier 'name' has already been declared
at createScript ( vm.js:80:10)
at Object.runInThisContext ( vm.js:139:10)
at Module._compile ( module.js:599:28)
at Object.Module._extensions.. js ( module.js:646:10)
at Module.load ( module.js:554:32)
at tryModuleLoad ( module.js:497:12)
at Function.Module._load ( module.js:489:3)
at Function.Module.runMain ( module.js:676:10)
at startup ( bootstrap_node.js:187:16)
at bootstrap_node.js:608:3
因为
obj
对象的
name
属性必须在解构中定义
name
变量进行获取,那么这一冲突就无法避免。这个时候可以通过重命名的方式来解决这样的问题,如下代码所示:
const obj = {
name: '拉勾大前端' ,
age: 3
}
const name = '拉勾大前端'
const {
name: objName
} = obj
console. log ( objName)
如上述代码所示,解构中原本的
name
对应着
obj
对象的
name
属性,
objName
是重命名的变量名,从而解决了同名的冲突。如下图所示:
今日分享截止到这里,明天继续更新后续部分:模板字符串、参数默认值、剩余参数等。
记录:2020/11/03
下一篇:模板字符串、参数默认值、剩余参数