美文网首页
es6 变量声明与解构

es6 变量声明与解构

作者: Super曲江龙Kimi | 来源:发表于2019-08-25 16:30 被阅读0次

    1. 变量声明

    let和const是es6新增的两种声明变量的方式。比var更严格更完善。所以代码中都推荐使用let或者const而不是var来声明

    (1) let 、const

    <1> 不存在变量提升

    var定义的变量会存在变量提升,而let和const不允许使用没有声明过的变量

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    

    只要使用let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错,称为“暂时性死区(TDZ)”

    if (true) {
      // TDZ开始
      tmp = 'abc'; // ReferenceError
      console.log(tmp); // ReferenceError
    
      let tmp; // TDZ结束
      console.log(tmp); // undefined
    
      tmp = 123;
      console.log(tmp); // 123
    }
    

    <2> 不允许重复声明

    使用let 或者 const声明过的变量,就不允许再次声明了。

    var a = 1;
    var a = 2;
    
    let b = 1;
    let b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
    

    <3> const

    const 代表常量的意思,一旦声明,就必须立即初始化,不能留到以后赋值,并且常量的值不能改变。

    const a = 2;
    a = 3; // // TypeError: Assignment to constant variable.
    
    const foo; // // SyntaxError: Missing initializer in const declaration
    

    (3)块级作用域

    ES6 引入了块级作用域,在块级作用域中使用let、const声明的变量在块级作用域之外是访问不到的

    {
      let n = 5;
      if (true) {
        let n = 10;
        {
          let n = 20;
        }
      }
    }
    

    经过babel转换后

    "use strict";
    
    {
      var n = 5;
    
      if (true) {
        var n = 10;
        {
          var n = 20;
        }
      }
    }
    

    ·

    2. 解构赋值

    (1)数组的解构赋值

    let [a, b, c] = [1, 2, 3];
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    let [ , , third] = ["foo", "bar", "baz"]; // 可以有省略值
    let [head, ...tail] = [1, 2, 3, 4];
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b' 可以有默认值
    

    如果解构不成功,变量的值就等于undefined。

    let [x, y, ...z] = ['a'];
    x // "a"
    y // undefined
    z // []
    

    只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。set、map...

    let [x, y, z] = new Set(['a', 'b', 'c']);
    x // "a"
    

    用babel转换后,原理其实就是依次赋值的语法糖

    var _ref = new Set(['a', 'b', 'c']),
        x = _ref[0],
        y = _ref[1],
        z = _ref[2];
    

    (2)对象的解构赋值

    可以重命名
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    
    也可以嵌套赋值, 这里的p是模式,而不是变量,不会赋值
    let obj = {
      p: [
        'Hello',
        { y: 'World' }
      ]
    };
    
    let { p: [x, { y }] } = obj;
    
    可以多次解构
    const node = {
      loc: {
        start: {
          line: 1,
          column: 5
        }
      }
    };
    
    let { loc, loc: { start }, loc: { start: { line }} } = node;
    line // 1
    loc  // Object {start: Object}
    start // Object {line: 1, column: 5}
    
    也可以嵌套直接赋值
    let obj = {};
    let arr = [];
    
    ({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
    
    obj // {prop:123}
    arr // [true]
    

    用babel转换后如下:

    var obj = {};
    var arr = [];
    var _foo$bar = {
      foo: 123,
      bar: true
    };
    obj.prop = _foo$bar.foo;
    arr[0] = _foo$bar.bar;
    obj; // {prop:123}
    
    arr; // [true]
    

    原理很简单,其实就和之前一个个属性的取一样。那么当热也可以取到继承的值

    const obj1 = {};
    const obj2 = { foo: 'bar' };
    Object.setPrototypeOf(obj1, obj2);
    
    const { foo } = obj1;
    foo // "bar"
    

    (3)字符串的解构赋值

    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"
    

    用babel转换后

    var _hello = 'hello',
        a = _hello[0],
        b = _hello[1],
        c = _hello[2],
        d = _hello[3],
        e = _hello[4];
    

    (4)数值和布尔值的解构赋值

    解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。

    let {toString: s} = 123;
    s === Number.prototype.toString // true
    
    let {toString: s} = true;
    s === Boolean.prototype.toString // true
    
    undefined、null转换不成对象,所以报错
    let { prop: x } = undefined; // TypeError 
    let { prop: y } = null; // TypeError
    

    (5)函数参数的解构赋值

    function add([x, y]){
      return x + y;
    }
    
    add([1, 2]); // 3
    
    二维数组的降维运算
    [[1, 2], [3, 4]].map(([a, b]) => a + b);
    
    
    function move({x = 0, y = 0} = {}) {
      return [x, y];
    }
    
    move({x: 3, y: 8}); // [3, 8]
    move({x: 3}); // [3, 0]
    move({}); // [0, 0]
    move(); // [0, 0]
    

    经过babel转换后

    // void 0 相当于一个函数什么也都不返回 void 0 === undefined;
    function move(_temp) {
      var _ref = _temp === void 0 ? {} : _temp,
          _ref$x = _ref.x,
          x = _ref$x === void 0 ? 0 : _ref$x,
          _ref$y = _ref.y,
          y = _ref$y === void 0 ? 0 : _ref$y;
    
      return [x, y];
    }
    

    (6)解构的使用场景

    交换变量的值

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];
    

    遍历 Map 结构

    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    
    for (let [key, value] of map) {
      console.log(key + " is " + value);
    }
    // first is hello
    // second is world
    

    相关文章

      网友评论

          本文标题:es6 变量声明与解构

          本文链接:https://www.haomeiwen.com/subject/rabhectx.html