ES6的常用特性--声明与表达式

91 阅读5分钟

ECMAScript是ECMA International定义的商标脚本语言规范。 创建它是为了标准化JavaScript。ES脚本语言具有许多实现,流行的实现是JavaScript。ECMAScript标准的第六版是ES6或ECMAScript6

1、let与const

- let

(1).基本用法

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

    {
      let a = 10;
      var b = 1;
    }
    a; // ReferenceError: a is not defined.
    b; // 1

(2).不能重复声明

let 不允许在相同作用域内,重复声明同一个变量

   function func() {
      var a = 10;
      let a = 1;
   }
   func(); //Identifier 'a' has already been declared
    function func() {
      let a = 10;
      let a = 1;
    }
    func(); //Identifier 'a' has already been declared

(3).不存在变量提升

var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined。 let 命令改变了语法行为,它所声明的变量一定要在声明后使用,否则会报错

    console.log(foo); //undefined
    var foo = 2;
    console.log(bar); // ReferenceError:Cannot access 'bar' before initialization
    let bar = 2;

(4).暂时性死区

ES6规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前使用这些变量,就会报错。这在语法上称为 “暂时性死区”

var tmp = 123;
    if (true) {
      tmp = "abc"; // ReferenceError:Cannot access 'tmp' before initialization
      let tmp;
    }

Tips“暂时性死区”的本质就是:只要一进入当前作用域,所要使用的变量就已经存在了,但不可获取(否则报错),只有等到声明的那一行代码出现,才可以获取和使用

- const

const命令的用法和let相似,最大不同点就是:const声明一个只读的常量。一旦声明,常量的值就不能改变

Tips:这个不可改变的是指针,所以对于const声明的对象和数组还是可以改变的

2、 变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)

1、数组的解构赋值

(1)基本用法

    // 之前,为变量赋值,可以直接指定值
    let a = 1;
    let b = 2;
    let c = 3;

    // ES6中允许这样
    let [a, b, c] = [1, 2, 3]; // 可以从数组中提取值,按照对应位置,对变量赋值。
    //也可以使用嵌套数组的方式进行解构
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    foo; // 1
    bar; // 2
    baz; // 3

    let [, , third] = ["foo", "bar", "baz"];
    third; // "baz"

(2)默认值

解构赋值允许指定默认值

    let [foo = true] = [];
    foo; // true

    let [x, y = "b"] = ["a"];
    x; //'a'
    y; //'b'

默认值可以引用解构赋值的其他变量,但该变量必须已经声明

    let [x = y, y = 1] = []; // ReferenceError: y is not defined -- let的暂时性死区
    let [x = 1, y = x] = [1, 2];
2、对象的解构赋值

(1)基本用法

    let { bar, foo } = { foo: "aaa", bar: "bbb" };
    foo; // "aaa"
    bar; // "bbb"

    let { baz } = { foo: "aaa", bar: "bbb" };
    baz; // undefined

对象的解构与数组的解构,一个重要的不同点在于: 数组元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量名与属性同名,才能取到正确的值。

如果没有与变量名对应的属性名,导致取不到值,最后等于undefined

Tips:变量名和属性名不一样

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"

对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量

(2)默认值

对象的解构也可以指定默认值。默认值生效的条件是对象的属性值严格等于 undefined

  let {x, y = 5} = {x: 1};
  x;// 1
  y;// 5 

Tips:已经声明的变量用于解构赋值需要注意

    let x;
    {x} = {x:1};
    //会报错,JavaScript引擎会将 {x} 理解为一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。

    //正确的写法,将需要解构的部分用括号()包起来
    let x;
    ({x} = {x:1}); //1
3、字符串解构赋值

字符串也可以解构赋值,被转换成了一个类似数组的对象

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
4、数值和布尔值解构赋值

解构赋值时,如果等号右边是数值和布尔值,则会先转化为对象

    let { toString: s } = 123;
    s === Number.prototype.toString; // true

    let { toString: s } = true;
    s === Boolean.prototype.toString; // true

解构赋值的规则是:只要等号右边的值不是对象或数组,就先将其转化为对象。 由于 undefined 和 null 无法转化为对象,所以对他们进行解构赋值都会报错

5、 函数参数的解构赋值
    function add([x, y]) {
      return x + y;
    }

    add([1, 2]); // 3
    
    [[1, 2],[3, 4],].map(([a, b]) => a + b);
    // [ 3, 7 ]

函数 add 的参数看似是一个数组,但在传入参数时,数组参数就解构为变量 x 和 y。对于函数内部代码来说,参数就是 x 和 y

Tips:函数参数的解构也可以使用默认参数,如下:

    function decon({ x = 0, y = 0 } = {}) {
      return [x, y];
    }
    decon({ x: 3, y: 8 }); // [3, 8]
    decon({ x: 3 }); // [3, 0]
    decon({}); // [0, 0]
    decon(); // [0, 0]

函数 decon 的参数是一个对象,通过对这个对象进行解构,得到变量 x 和 y 的值。如果解构失败,x 和 y 等于默认值

Tips:还有一种指定默认值的写法:

    function decon({ x, y } = { x: 0, y: 0 }) {
      return [x, y];
    }

    decon({ x: 3, y: 8 }); // [3, 8]
    decon({ x: 3 }); // [3, undefined]
    decon({}); // [undefined, undefined]
    decon(); // [0, 0]

为函数 decon 的参数指定默认值,而不是为变量 x 和 y 指定默认值