zoukankan      html  css  js  c++  java
  • 数组的解构赋值与yield

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

    基本用法:

    1、

    let [a,b,c]=[1,2,3];

    a=1,b=2,c=3

    2、

    let [a,[b,[c]]]=[1,[2,[3]]];//a=1,b=2,c=3
    let [,,d]=[3,4,5];//d=5
    let [e,,f]=[6,7,8,9];//e=6,f=8
    let [g,h,...i]=[10,11,12,13];//g=10,h=11,i=[12,13],...i之后不能再有变量,否则报错
    let [j,k,...l]=[14];//j=14,k='undefined',l=[]

    如果解构不成功,变量的值就等于undefined,上面的k就是解构不成功,let [k]=[]也会解构不成功;而let [...k]=[]则会成功,因为k是个数组,此时k=[]

    还有一种情况是不完全解构,即等号左边的模式只匹配一部分等号右边的数组,这种情况下,解构依然可以成功,例如 let [a,b]=[1,2,3];//a=1,b=2

    3、

    如果等号的右边不是数组(或者严格地说,不是可遍历的结构),那么将会报错。例如let [a]=1;let [b]=false;let [c]={};let [d]=undefined;这些都会报错,因为都不具备Iterator 接口

    对于Set结构,也可以使用数组的解构赋值

    let [a, b, c] = new Set([1, 2, 3]);//a=1,b=2,c=3

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

      function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            yield x;
            [x, y] = [y, x + y];
          }
        }
        let [a, b, c, d, e, f, g] = fibs();//a=0,b=1,c=1,d=2,e=3,f=5,g=8

    这里遇到了yield,顺便学一下

    yield这个关键字是用来暂停和恢复一个遍历器函数(的运行)的,每次暂停会返回yield后面的值,比如上面的yield x;每次运行到这里都会暂停,然后返回x的值。
    a、把上面的yield x改一下
     function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            yield [x, y];
            [x, y] = [y, x + y];
          }
        }
        let [a, b, c, d, e, f, g] = fibs();
        console.log("a=", a);
        console.log("b=", b);
        console.log("c=", c);
        console.log("d=", d);
        console.log("e=", e);
        console.log("f=", f);
        console.log("g=", g);

    结果如下图:

     b、

    function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            yield x;
            [x, y] = [y, x + y];
            return;
          }
        }
        let func = fibs();
        console.log("func=", func);
        let a = func.next();
        console.log("a=", a);
        let b = func.next();
        console.log("b=", b);

    结果如下图:

    第一次调用let a=func.next()是运行到yield x,返回x的值,暂停遍历,不会执行return,所以a的值是{value: 0, done: false},返回的值为x,x=0,value:0,遍历没结束,done:false;

    第二次调用let b = func.next()是运行到return,遍历结束,return没有返回值,所以是undefined,遍历结束,所以done:true,b= {value: undefined, done: true}

    c、

     function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            yield [x, y];
            [x, y] = [y, x + y];
            return y;
          }
        }
        let func = fibs();
        console.log("func=", func);
        let a = func.next();
        console.log("a=", a);
        let b = func.next();
        console.log("b=", b);

    d、

      function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            let z = yield x;
            console.log("z=", z);
            y = z + y;
            return y;
          }
        }
        let func = fibs();
        console.log("func=", func);
        let a = func.next();
        console.log("a=", a);
        let b = func.next();
        console.log("b=", b);

    上面代码let a = func.next();会在yield x暂停,然后let b = func.next();并没有传参数进去,所以z= undefined
      function* fibs() {
          let x = 0;
          let y = 1;
          while (true) {
            let z = yield x;
            console.log("z=", z);
            y = z + y;
            return y;
          }
        }
        let func = fibs();
        console.log("func=", func);
        let a = func.next();
        console.log("a=", a);
        let b = func.next(2);//传2进去
        console.log("b=", b);

    传参数进去时,会把参数yield暂停的那一块替换成传进去的参数,此时let z=2;但是第一次调用let a = func.next();是不能在next()里面传参数的

      yield总结:
    1. 只能在Generator函数内部使用
    2. 运行.next(),遇到一个yield命令,就暂停
    3. .next()的返回值表示一个状态{value,done}
    4. 再运行.next(),从之前遇到的那个yield [表达式]处恢复运行
    5. 当.next()传参的时候,yield [表达式]整个被替换为传入的参数

     4、默认值

    解构赋值允许指定默认值

    let [a=1]=[];//a=1
    let [b,c=2]=[1];//b=1,c=2
    let [e,f=3]=[4,undefined];//e=4,f=3

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

    let [a=1]=[undefined];//a=1
    let [b=1]=[null];//b=null

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

    如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。

    function func(){
        console.log("111"); 
    }
    
    let [a=func()]=[1];

    上面代码中,因为a能取到值,所以函数func根本不会执行。

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

    let [a=1,b=a]=[];//a=1,b=1
    let [c=1,d=c]=[2];//c=2,d=2
    let [e=1,f=e]=[2,3];//e=2,f=3
    let [g=h,h=1]=[];//ReferenceError: h is not defined

    上面最后一个表达式之所以会报错,是因为gh做默认值时,h还没有声明。

  • 相关阅读:
    原码/反码/补码详解
    树剖LCA讲解
    code vs 2166 Bessie的体重问题
    code vs 3376 符号三角形
    洛谷 P3078 [USACO13MAR]扑克牌型Poker Hands
    vjudge B
    POJ 1013 Counterfeit Dollar
    POJ 1008 Maya Calendar
    POJ 1006 Biorhythms
    POJ 3252 Round Numbers
  • 原文地址:https://www.cnblogs.com/pzw23/p/12936461.html
Copyright © 2011-2022 走看看