深入理解es6学习笔记(一)

131 阅读7分钟

第一章 块级作用域绑定

1.临时死区(Temporal Dead Zone)

使用let或者const声明时,Javascript引擎扫描代码时将这些声明放在TDZ中,访问TDZ中变量会触发运行时错误。只有执行过变量声明语句之后,变量才会从TDZ中移出,方可正常访问。

2.循环中的块级作用域绑定

在循环中使用let或者const声明,每次循环迭代都会创建一个新变量,并以之前迭代中同名变量的值将其初始化。
简化了用var声明时需要用IIFE实现循环变量i副本的做法

第二章 字符串和正则表达式

一、更好的Unicode支持

字符串里的自字符有两种,一种是由一个编码单元16位表示的BMP字符,另一种是由两个编码单元32位表示的辅助平面符。在es5中,所有的字符串都是基于16位编码单元,es6新增了完全支持UFT-16的方法。

1.codePointAt() String.fromCodePoint()

两者可看成是完整版的charCodeAt() String.fromCharCode()
只有传递非BMP的字符串或者码数时执行结果两者才会不同

2.normalize() => Unicode标准化

在国际化的应用中这个方法会用到,比较字符串之前先标准化

3.正则表达式u修饰符

正则表达式添加u修饰符,从编码单元操作模式切换为字符模式。需要注意的是这个是语法层面的变更,使用前最安全的做法是检测当前引擎是否支持
如果代码要运行在老式的JavaScript引擎中,使用RegExp构造函数!避免发生语法错误

4.其他字符串变更

新增includes() startsWith() endsWith() 传参只支持字符串,传入正则会触发错误。indexOf()和lastIndexOf()支持传入正则 新增repeat()

二、其他正则语法变更

1.y修饰符

会影响正则表达式中的sticky属性,当开始匹配会通知从正则表达式的lastIndex属性开始,没能匹配成功则停止匹配。

  • 只有调用exec()和test()这些正则表达式对象的方法才会涉及lastIndex属性,调用字符串的方法例如match()不会触发粘滞行为
  • 对于粘滞正则表达式,如果正则表达是中含有^,当lastIndex的值在单行模式下不为0或者在多行模式下不对应于行首,粘滞的表达式永远不会匹配成功
  • 正则表达式属性sticky属性为true=>y修饰符存在

2.正则表达式复制

es6中复制正则表达式,可通过第二个参数修改其修饰符

let re1 = /ab/i,
re2 = new RegExp(re1,'g') // es5中抛出错误 es6中正常

3.flags属性

获取正则表达式使用的修饰符

三、模版字面量

标签模版--标签可以是一个函数,第一个参数是一个数组,包含Javascript解释过的字面量字符串,不定参数是每个占位符的解释值 在模版字面量中使用原始值--String.raw()

第三章 函数

一、函数形参的默认值

1.默认参数值对arguments对象的影响

es5非严格模式下,函数命名参数的变化会同步更新在arguments对象中
es5严格模式下,无论参数怎么变化,arguments对象不再随之改变
es6中,默认参数值不会出现在arguments对象中

2.默认参数表达式

对于默认参数表达式,只有调用函数在用到默认参数表达式时才会去调用,初次解析函数声明时不会调用。
默认参数存在临时死区,定义参数时会为每个参数创建一个新的标识符绑定,该绑定在初始化之前不可被引用,当调用函数时,会通过传入的值或者参数的默认值初始化该参数 参数的默认值不可访问函数体内声明的变量

function add(first = second, second) {
    return first + second
}
console.log(add(1,1)) //2
console.log(add(undefined,1)) // 抛出错误

二、name属性

es6为所有函数新增了name属性,getter和setter函数的名称中有get set前缀,通过bind()创建的函数名称中带有bound前缀,通过Function构造函数创建的函数其名称是anonymous
!!函数name属性的值不一定引用同名变量,只是协助调试的信息,不可使用name属性获取对函数的引用

三、明确函数的多重用途

Javascript函数调用有两个不同的内部方法:[[Call]] [[Construct]]。当使用new关键字调用函数时执行[[Construct]]函数,它负责创建实例的新对象,然后再执行函数体,将this绑定在实例上;不通过new就会执行[[Call]]函数,直接执行代码中的函数体。
具有[[Construct]]的函数--构造函数

1.es5中判断函数被调用的方法

在es5中,确定一个函数是否通过new关键字调用,使用instanceof。但是存在缺点,无法区分new还是调用call()[或者apply()]

2.元属性 new.target

元属性--非对象的属性,可以提供非对象目标的补充信息
可以通过检查new.target是否被定义才确定韩式是否通过new调用

四、块级函数

  • 块级函数与let函数表达式类似,在代码块中,块级函数会被提升至代码块的顶部,而let定义的函数表达式不会提升
  • 非严格环境中,块级函数会提升至外围函数或则全局作用域的顶部

五、箭头函数

  • 没有this、super、arguments和new.target绑定。箭头函数的this由外围最近一层非箭头函数决定,不能通过call()、apply()或bind()来改变
  • 不能通过new关键字调用,没有[[Construct]]方法
  • 没有原型
  • 不支持重复的命名参数
    对于箭头函数的立即执行函数表达式,小括号只包裹箭头函数定义

六、尾调用优化

尾调用是指函数作为另一个函数的最后一条语句被调用。在es5引擎中,尾调用的实现与其他函数类似:创建一个新的栈帧并将其推入调用栈来表示函数调用。在循环调用中未用完的栈帧都被保存在内存中,当调用帧过大时会造成程序问题。
es6在严格模式下满足以下条件,尾调用会清除并重用当前栈帧:
写递归函数时,如果递归函数的计算量够大,使用这个优化可以大幅提升程序性能

  • 尾调用不访问当前栈帧的变量(函数不是一个闭包)
  • 在函数内部尾调用是最后一条语句
  • 尾调用的结果作为函数值返回

第四章、扩展对象的功能性

一、新增方法

1.Object.is()

弥补全等运算符的不准确运算:例如+0和-0 NaN和NaN

2.Object.assign()

接受任意数量的源对象并按指定顺序将属性复制到接收对象中。由于该方法执行了赋值操作,提供者的访问其属性最终会转变为接收对象中的一个数据属性。

二、自有属性枚举顺序

es6严格规定对象的自有属性被枚举的返回顺序,影响到Object.getOwnPropertyNames() Reflect.ownKeys Object.assign()

  • 所有数字键按升序排列
  • 所有字符键按照他们被加入对象的顺序排列
  • 所有symbol按照他们被加入对象的顺序排列

三、增强对象原型

1.改变对象的原型 增加方法Object.setPropertyOf()

2.简化原型访问的Super引用

super引用指向对象原型的指针。但是必须要在使用简写方法的对象中使用Super引用

let friend = {
    getGreeting:function(){ //这里要使用简写方法 getGreeting()
        return super.getGreeting() + ",hi!"// 语法错误
    }
}

3.方法的正式定义

es6中将方法正式定义为一个函数,会有一个内部的[[HomeObject]]属性来容纳这个方法从属的对象。Super的所有引用都是通过这个属性来确定后续的运行过程。