一、let指示
基本上用语
ES6追加了let指示,用以新闻稿表达式,用语类似于与var,但所新闻稿的表达式,只在let指示所处的标识符块内有效率。
依次用let和var新闻稿三个表达式,接着在标识符块外初始化三个表达式,结论let新闻稿三个表达式收起,var新闻稿表达式回到了恰当的值,这表明let新闻稿的表达式有效率覆盖范围只在其所处的标识符块中有效率。
for循环式计时器,就很适宜采用let指示。
计时器i只在for循环式胃部有效率,在循环式导管提及就会报错。
假如采用var,则输入为10,
表达式i是var新闻稿的,在自上而下覆盖范围内有效率,因此自上而下多于两个表达式i,每一次循环式,表达式i的值单厢出现出现改变,而循环式内被赋给字符串a的表达式外部的console.log(i),里头的i对准的是自上而下的i。也是说,大部份字符串a的核心成员里头的i,对准的都是同一i,引致运转时输入的是最终半程的i的值,也是 10。
假如谁用let新闻稿,新闻稿的表达式仅在块级促进作用皮先卡有效率,最终输入的值是6.
下面标识符中,表达式i是let新闻稿的,现阶段的i只在此轮循环式有效率,因此每一次循环式的i只不过都是两个捷伊表达式,因此最终输入的是6。你可能会问,假如每半程循环式的表达式i都是再次新闻稿的,那它是不是晓得上半程循环式的值,从而排序出此轮循环式的值?这原因在于 JavaScript 发动机外部会读懂上半程循环式的值,初始化此轮的表达式i时,就在上半程循环式的基础上展开排序
另外for循环式还有两个特别之处,设置循环式表达式的那部分是两个父促进作用域,而循环式导管部则是两个单独的子促进作用域。
下面标识符恰当运转,输入了 3 次abc。这表明表达式外部的表达式i与循环式表达式i不在同一促进作用域,有各自单独的促进作用域(同一促进作用域不可采用let重复新闻稿同一表达式)。
不存在表达式提升
var指示会出现表达式提升现象,即表达式可以在新闻稿之前采用,值为undefined,按照一般的逻辑,表达式必须在新闻稿语句之后才可以采用。
为了纠正这种现象,let指示出现改变了语法行为,它所新闻稿的变量一定要在新闻稿后采用,否则收起。
下面标识符中,表达式foo用var指示新闻稿,会出现表达式提升,即脚本开始运转时,表达式foo已经存在了,但没有值,因此会输入undefined。表达式bar用let指示新闻稿,不会出现表达式提升。这表示在新闻稿它之前,表达式bar是不存在的,这时假如用到它,就会抛出两个错误。
暂时性死区
只要块级促进作用皮先卡存在let指示,它所新闻稿的表达式就“绑定”(binding)这个区域,不再受外部的影响。
下面标识符中,存在自上而下表达式tmp,但块级促进作用皮先卡let又新闻稿了两个局部表达式tmp,引致后者绑定这个块级促进作用域,因此在let新闻稿表达式前,对tmp赋值会收起。
ES6 明确规定,假如区块中存在let和const指示,这个区块对这些指示新闻稿的表达式,从一开始就形成了封闭促进作用域。凡是在新闻稿之前就采用这些表达式,就会收起。
总之,在标识符块内,采用let指示新闻稿表达式之前,该表达式都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)
下面标识符中,在let指示新闻稿表达式tmp之前,都属于表达式tmp的“死区”。
“暂时性死区”也意味着typeof不再是两个百分之百安全的操作。
上面标识符中,表达式x采用let指示新闻稿,因此在新闻稿之前,都属于x的“死区”,只要用到该表达式就会收起。因此,typeof运转时就会抛出两个ReferenceError。
作为比较,假如两个表达式根本没有被新闻稿,采用typeof反而不会收起。
下面标识符中,undeclared_variable是两个不存在的表达式名,结论回到“undefined”。因此,在没有let之前,typeof运算符是百分之百安全的,永远不会收起。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯,表达式一定要在新闻稿之后采用,否则就收起。
有些死区比较隐蔽,不太容易发现,
下面标识符中,初始化bar表达式之因此收起(某些实现可能不收起),原因在于参数x默认值等于另两个参数y,而此时y还没有新闻稿,属于“死区”。假如y的默认值是x,就不会收起,因为此时x已经新闻稿了。
另外,下面的标识符也会收起,与var的行为不同。
下面标识符收起,也原因在于暂时性死区。采用let新闻稿表达式时,只要表达式在还没有新闻稿完成前采用,就会收起。下面这行就属于这个情况,在表达式x的新闻稿语句还没有执行完成前,就去取x的值,引致收起”x 未定义“
ES6 规定暂时性死区和let、const语句不出现表达式提升,主要是为了减少运转时错误,防止在表达式新闻稿前就采用这个表达式,进而引致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。
总之,暂时性死区
不允许重复新闻稿
let不允许在相同促进作用皮先卡重复新闻稿同一表达式,
因此不能在表达式外部重复新闻稿参数。
二、块级促进作用域
需要块级促进作用域的原因。
ES6多于自上而下促进作用域和表达式促进作用域,没有块级促进作用域。这种现象引致很多不合理的场景。
第一种情况,内层表达式可能会覆盖外层表达式。
下面标识符的原意是,if标识符块的外部采用外层的tmp表达式,外部采用内层的tmp表达式。但,表达式f执行后,输入结论为undefined,原因在于表达式提升(表达式新闻稿提升),引致内层的tmp表达式覆盖了外层的tmp表达式。
第二种情况,用以计数的循环式表达式泄露为自上而下表达式。
下面表达式i只用以控制循环式表达式,但循环式结束后其并没有消失,泄露了自上而下表达式。
ES6的块级促进作用域
let实际上为JS追加了块级促进作用域
表示外层标识符快不受内层标识符块的影响,如果两次都采用var定义表达式n,最终输入的值才是 10。
ES6允许块级促进作用域的任意嵌套。
下面标识符采用了两个五层的 块级促进作用域,每一层都是两个单独的促进作用域,第四层促进作用域无法读取第五层促进作用域的外部表达式。
内层促进作用域可以定义外层促进作用域的同名表达式。
块级促进作用域的出现,实际上使得获得广泛应用的匿名立即执行表达式表达式(匿名 IIFE)不再必要了。
块级促进作用域与表达式新闻稿
ES5规定,表达式之能在顶层促进作用域和表达式促进作用域之中声明,不能在块级促进作用域中新闻稿。
根据ES5规定,下面两种表达式新闻稿都是非法的,
但浏览器并没有这个规定,为了兼容以前的旧标识符,还是支持在块级促进作用域中新闻稿表达式,
ES6引入了块级促进作用域,明确允许在块级促进作用域中声明表达式,规定:块级促进作用域中表达式新闻稿语句行为类似于于let,在块级促进作用域外不可提及。
下面标识符在 ES5 中运转,会得到“I am inside!”,因为在if内新闻稿的表达式f会被提升到表达式头部,实际运转的代码如下。
ES6 就完全不一样了,理论上会得到“I am outside!”。因为块级促进作用皮先卡新闻稿的表达式类似于于let,对促进作用域之外没有影响。但,假如你真的在 ES6 浏览器中运转一下下面的标识符,是会报错的,这是为什么呢?
原来,假如出现改变了块级促进作用皮先卡新闻稿的表达式的处理规则,显然会对老标识符产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里头规定,浏览器的实现可以不遵守下面的规定,有自己的行为方式。
允许块级促进作用皮先卡新闻稿表达式表达式新闻稿类似于于var,即会提升到自上而下促进作用域或表达式促进作用域的头部。同时,表达式新闻稿还会提升到所处块级促进作用域的头部。下面规则,只对ES6的浏览器实现有效率,其他环境下则不适用,还是将块级促进作用域类似于于let表达式。
根据这三条规则,浏览器的 ES6 环境中,块级促进作用皮先卡新闻稿的表达式,行为类似于于var新闻稿的表达式。下面的例子实际运转的标识符如下。
考虑到环境引致的行为差异太大,应避免在块级作用皮先卡新闻稿表达式,假如确实需要,也应该写成表达式表达式,而不是表达式新闻稿。
需要注意:ES6的块级促进作用域必须有花括号,假如没有花括号,JS发动机就认为不存在块级促进作用域。
表达式新闻稿也是如此,严格情况下,表达式只能新闻稿现阶段促进作用域的顶层。
总结:日常积累,强化学习,最终运用到实践中去。