ES6基本语法

let命令

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

    {
       var a = 10;
       let b = 20;
    }
    console.log(a)//10
    console.log(b)//ReferenceError: b is not defined.
    • 不存在变量提升
      var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
      //var 的情况
      console.log(a);//undefined
      var a = 10;
      //let的情况
      console.log(b);//报错ReferenceError
      let b = 2o;
      

    由于变量a 是由var声明的,所以存在变量提升,所以打印出来的值为undefined;由于变量b是由let声明的,不存在变量提升,所以报错;

    • 暂时性死区
      只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

数组的解构赋值

  • 数组的解构赋值允许默认值

    let [foo = true] = [];
    console.log(foo) //true

    注意:ES6内部使用严格相等运算符(===),判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的

    let [x = 1] =[undefined]
    console.log(1)//1
    
    let [y = 1] = [null]
    console.log(y)//null

    上面代码中,如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined

    • 如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
      function f() {
          console.log('aaa')
      }
      let [x = f()] = [1]

    上面代码中,因为x能取到值,所以函数f不会执行,上面的代码其实等价于下面的代码

    let x;
    if([1][0] === undefined){
        x = f();
    } else{
        x = [1][0]
    }
  • 默认值可以引用解构赋值的其他变量,但该变量必须已经声明。

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

对象的解构赋值

  • 对象的解构赋值与数组有一个重要的不同。数组的元素是按次序排序的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到值。

    let {foo,far} = {foo:'23',far:'45'};
    console.log(foo)//23
    console.log(foo)//45

    如果变量名与属性名不一致,必须写成下面这样。

    let {foo:baz} = {foo:'aaa'}
    console.log(baz)//aaa

    上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
    也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
  • 与数组一样,解构也可以用于嵌套结构的对象。

    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}

    上面代码有三次解构赋值,分别是对loc、start、line三个属性的解构赋值。注意,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。

  • 如果要将一个已经声明的变量用于解构赋值,必须非常小心。

    //错误写法
    let x;
    {x} = {1};
    //SyntaxError: syntax error

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

    //正确写法
    let x;
    ({x} = {1})

    上面代码将整个解构赋值语句,放在一个圆括号里面,就可以正确执行。关于圆括号与解构赋值的关系,参见下文。

    解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式

  • 应用场景 对象的结构赋值,可以很方便的将现有对象的方法,赋值到某个对应的变量。

    let {log,sin,cos} = Math;

    上面代码将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。
    由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。

    let arr = [1, 2, 3];
    let {0 : first, [arr.length - 1] : last} = arr;
    first // 1
    last // 3

    上面代码对数组进行对象解构。数组arr的0键对应的值是1,[arr.length - 1]就是2键,对应的值是3。

字符串的解构赋值

  • 字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

    let [a,b,c,d] = 'love';
    a // l
    b // o
    c // v
    d // e

    类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

    let {length : len} = "love";
    len // 4

    数值和布尔值的解构赋值

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

      let {prop:x} = undefined; //TypeError
      let {prop:y} = null; //TypeError

      ## 函数参数的解构
      函数的参数也可以使用解构赋值

      function add([a,b]) {
      return a + b;
      }
      add([1,2]) //3

      另外一个例子

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

      注意下面的写法会得到不一样的结果

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

      上面的代码是为函数move指定默认值,而不是为变量x和y指定默认值,所以会得到与前一种写法不同的结果
      undefined就会触发函数参数的默认值

      [1,undefined,2].map((x = 'yes') => x) //[1, yes, 2]

    圆括号问题

    解构赋值虽然很方便,但是解析起来并不容易。对于编译器来说,一个式子到底是模式,还是表达式,没有办法从一开始就知道,必须解析到(或解析不到)等号才能知道。

    由此带来的问题是,如果模式中出现圆括号怎么处理。ES6 的规则是,只要有可能导致解构的歧义,就不得使用圆括号。

    但是,这条规则实际上不那么容易辨别,处理起来相当麻烦。因此,建议只要有可能,就不要在模式中放置圆括号。
    不能使用圆括号的情况
    变量声明语句

    //全部报错
    let [(a)] = [2];
    let ({x: c}) = {};
    let {(x: c)} = {};
    let {(x): c} = {};
    let { o: ({ p: p }) } = { o: { p: 2 } };

    以上6个语句都会报错,因为它们都是变量声明语句,模式不能使用圆括号。
    可以使用圆括号的情况
    可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。

    [(b)] = [3];
    ({p: (d)}) = {})
    

    用途

    (1)交换变量的值

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

    (2)从函数返回多个值

    //返回一个数组
    function example() {
        return [1, 2, 3]
    }
    let [a, b ,c] = example();

    (3)函数参数的定义

    function f([x, y]) {...}
    f([1, 2])

    (4)提取JSON数据

    let jsonData = {
        id: 2,
        userName:Anlon
    }
    let {id, userName} = jsonData;

    (5)函数参数的默认值

    jQuery.ajax = function (url, {
    async = true,
    beforeSend = function () {},
    cache = true,
    complete = function () {},
    crossDomain = false,
    global = true,
    // ... more config
    }) {
    // ... do stuff
    };

    指定参数的默认值,就避免了在函数体内部再写var foo = config.foo || ‘default foo’;这样的语句
    (6)遍历Map结构

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

    (7)输入指定的模块

    const { SourceMapConsumer, SourceNode } = require("source-map");

    Promise

    Promise是异步编程的一种解决方案
    Promise对象有以下两个特点
    (1) 对象的状态不受外界影响。promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,其他任何操作都无法改变这个状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值