ES6知识整理(一)

ES6知识整理(一)

http://es6.ruanyifeng.com/

ES6简介

ECMAScript 6.0,简称 ES6,是 JavaScript 语言的下一代标准,在 2015 年 6 月已经正式发布。目标是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

1、块级作用域

1)为什么需要块级作用域

ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理:

  • 内层变量可能会覆盖外层变量。
  • 用来计数的循环变量泄露为全局变量。

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

外层作用域无法读取内层作用域的变量。内层作用域可以定义外层作用域的同名变量。块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。

3)块级作用域与函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

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

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。根据这三条规则,在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量

考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。

4)do 表达式

本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值。现在有一个提案,使得块级作用域可以变为表达式,也就是说可以返回值,办法就是在块级作用域之前加上do,使它变为do表达式,然后就会返回内部最后执行的表达式的值。
let x = do {
  let t = f();
};

2、let命令(let实际上为 JavaScript 新增了块级作用域。)

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是let所声明的变量,只在let命令所在的代码块内有效,let声明的变量只在它所在的代码块有效。

<script>
        function letCode(){
            let sum=0;
            for(let i=0;i<10;i++) {
                sum+=i;
                console.log(i);  
            }
            console.log(i);
        }
        letCode();
</script>
第一个console.log(i)输出的结果是0,1,2,3,4,5,6,7,8,9
第二个console.log(i)输出的结果是i is not defined
<script>
        function letCode(){
            var sum=0;
            for(var i=0;i<10;i++) {
                sum+=i;
                console.log(i);  
            }
            console.log(i);
        }
        letCode();
</script>
第一个console.log(i)输出的结果是0,1,2,3,4,5,6,7,8,9
第二个console.log(i)输出的结果是10

注意:for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

注意:1)let不存在变量提升

var命令会发生”变量提升“现象,let命令改变了语法行为,所声明的变量一定要在声明后使用,否则报错。
console.log(a);
var a=123;
console.log(b);
let b=234;
console.log(a)的结果是undefined,因为发生了变量的提升,变量的声明var a会提升,所以结果是undefined
console.log(b)的结果是b is not defined,let不存在变量提升现象

注意:2)会形成暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。使用let声明变量时,只要变量在还没有声明完成前使用,就会报错。在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。比如:let x = x;结果就是x is not defined
tmp=123;
console.log(tmp);
打印的结果是123
tmp=123;
console.log(tmp);
let tmp;
console.log(tmp);
打印的结果是tmp is not defined,在let生命之前,都是tmp死区,只要用到这个变量就会报错,在没有let之前,typeof运算符是百分之百安全的。

ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

注意:3)不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。不能在函数内部重新声明参数。

function repeat(){
        var a=1;
        let a=2;
        }
repeat();
结果是报错,Uncaught SyntaxError: Identifier 'a' has already been declared
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章