ES6 learning (2)

Block-level scope

  ES5 only global scope and function scope, not block-level scope,

 

1  // inner layer may cover the outer variable variable 
2  
. 3  var tmp = new new a Date ();
 . 4  
. 5  function F () {
 . 6    the console.log (tmp);
 . 7    IF ( to false ) {
 . 8      var tmp = ' Hello World ' ;
 . 9    }
 10  }
 . 11  
12 is F (); // undefined
 13 is  
14  // used to calculate the loop variable as global variables leakage 
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 

 

 

  In fact, let const ES6 JavaScript added to the block-level scope, if let, the above-mentioned f () will be given, console.log (i) an error is reported, i is not defined

 

  ES6 allows any nested block-level scope

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

  

  Appears block-level scope, and actually makes the widely used self-executing anonymous function expressions (anonymous IIFE) is no longer necessary

 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

Guess you like

Origin www.cnblogs.com/newttt/p/11808899.html