• ES6学习(2)


    块级作用域

      ES5中只有全局作用域和函数作用域,没有块级作用域,

     1 //内层变量可能覆盖外层变量
     2 
     3 var tmp = new Date();
     4 
     5 function f() {
     6   console.log(tmp);
     7   if (false) {
     8     var tmp = 'hello world';
     9   }
    10 }
    11 
    12 f(); // undefined
    13 
    14 // 用来计算的循环变量泄漏为全局变量
    15 var s = 'hello';
    16 
    17 for (var i = 0; i < s.length; i++) {
    18   console.log(s[i]);
    19 }
    20 
    21 console.log(i); // 5 

      ES6中let const 实际上为JavaScript新增了的块级作用域,如果使用let,上述f()就会报错, console.log(i)则会报错,i is not defined

      ES6 允许块级作用域的任意嵌套

    1 {{{{
    2   {let insane = 'Hello World'}
    3   console.log(insane); // 报错
    4 }}}};
    5 
    6 {{{{
    7   let insane = 'Hello World';
    8   {let insane = 'Hello World'}
    9 }}}};

      

      块级作用域的出现,实际上使得广泛应用的匿名自执行函数表达式(匿名IIFE)不再必要

     1 // IIFE 写法
     2 (function () {
     3   var tmp = ...;
     4   ...
     5 }());
     6 
     7 // 块级作用域写法
     8 {
     9   let tmp = ...;
    10   ...
    11 }

    块级作用域与函数声明

      ES5 中规定, 函数只能在顶层作用域和函数作用域之中声明, 不能在块级作用域声明,

      ES6引入块级作用域,明确运行在块级作用域中声明函数, ES6 规定块级作用域之中,函数声明语句的行为类似let,在块级作用域之外不可引用

     1 function f() { console.log('I am outside!'); }
     2 
     3 (function () {
     4   if (false) {
     5     // 重复声明一次函数f
     6     function f() { console.log('I am inside!'); }
     7   }
     8 
     9   f();
    10 }());

      上面的代码在ES5中运行,会得到"I am inside!", 因为在if内声明的函数f会被提升到函数的头部

        而在ES6中就完全不一样了,因为块级作用域内声明的函数类似于let, 对于作用域之外没有影响, 但是运行一下上面的代码就会报错 

     1 // 浏览器的 ES6 环境
     2 function f() { console.log('I am outside!'); }
     3 
     4 (function () {
     5   if (false) {
     6     // 重复声明一次函数f
     7     function f() { console.log('I am inside!'); }
     8   }
     9 
    10   f();
    11 }());
    12 // Uncaught TypeError: f is not a function

    报错原因:

      因为如果改变了块级作用域内声明的函数的处理规则,那么对老代码会产生很大的影响,为了减轻因此产生的不兼容问题, ES6 中规定, 浏览器的实现可以不遵守上面的规定,而是有自己的行为方式,即:

      1\ 允许在块级作用域内声明函数, 2\ 函数声明类似var, 即会提升到全局作用域或函数作用域的头部, 3\ 勇士函数声明还会提升到所在块级作用域的头部

      注意 上面三条规则只对ES6的浏览器实现有线掐环境不遵守, 还是将块级作用域的函数声明当做let处理

    由于环境导致的行为差异太大, 还是应该避免在作用域内声明函数, 如果确实需要的话, 也应该写成函数表达式

      还需要注意的是, ES6的块级作用域必须有大括号, 如果没有JavaScript就认为不存在块级作用域

    1 // 第一种写法,报错
    2 if (true) let x = 1;
    3 
    4 // 第二种写法,不报错
    5 if (true) {
    6   let x = 1;
    7 }

    顶层对象的属性

      顶层对象在浏览器环境指的是window对象,在Node中值得是global对象,ES5中, 顶层对象的属性与全局变量是等价的, 这样会造成很多问题, 首先没法在编译时就报出变量未声明的错误, 只有运行时才能知道,其次程序员也可能不知不觉创建了全局变量,最后顶层对象的属性到处可以读写,这非常不利于模块化编程

      ES6 为了改变这一点,一方面规定为了兼容性, var命令和function命令声明的全局变量,依旧是顶层对象的属性,另一方面规定, let命令, const命令, class命令声明的全局变量, 不属于顶层对象的属性, 也就是说ES6开始全局变量将逐步与顶层对象的属性脱钩

      

     1 var a = 1;
     2 // 如果在 Node 的 REPL 环境,可以写成 global.a
     3 // 或者采用通用方法,写成 this.a
     4 window.a // 1
     5 
     6 let b = 1;
     7 window.b // undefined
     8 
     9 //有var声明的全局变量a 也属于顶层对象的属性, 因此window下有a属性,
    10 //全局变量b有let命令声明,所以他不是顶层对象属性, 返回undefined
  • 相关阅读:
    css设置页面内容不能被选中
    bootstrap栅格系统
    MVC框架
    类模板
    c++编译器模板机制剖析
    函数模板与函数重载
    函数模板当参数强化
    泛型编程—函数模板
    用友GRP-u8 注入-RCE漏洞复现
    漏洞代码调试(二):Strtus2-001代码分析调试
  • 原文地址:https://www.cnblogs.com/newttt/p/11808899.html
Copyright © 2020-2023  润新知