zoukankan      html  css  js  c++  java
  • ... 语法记录

    展开语法(Spread syntax)

    1. 可以在函数调用/数组构造时, 将数组表达式或者string在语法层面展开;
    2. 还可以在构造字面量对象时, 将对象表达式按key-value的方式展开。

    在函数调用时展开语法

    myFunction(...iterableObj); 在调用一个函数时提供数组或者对象时,将其展开

    // 数组迭代开作为函数的参数
    
    //es5
    function myFunction(x, y, z) { }
    var args = [0, 1, 2];
    myFunction.apply(null, args);
    
    // es6
    function myFunction(x, y, z) { }
    var args = [0, 1, 2];
    myFunction(...args);
    

    构造数组的展开语法

    数组的字面量构造

    下面这段代码是将数组快速变为一个新数组成员的方法,和参数列表的展开类似, ... 在构造字面量数组时, 可以在任意位置多次使用.注意和剩余参数的作为最后一项不同,它可以在任意位置

    var parts = ['shoulders','knees']; 
    var lyrics = ['head',... parts,'and','toes']; 
    // ["head", "shoulders", "knees", "and", "toes"]
    

    数组的浅拷贝

    数组的浅拷贝,只迭代拷贝出最外层

    var arr = [1, 2, 3];
    var arr2 = [...arr]; // like arr.slice()
    arr2.push(4); 
    
    // arr2 此时变成 [1, 2, 3, 4]
    // arr 不受影响
    

    数组的拼接

    unshift()方法中修改了原数组,而展开语法创建了一个新的数组来接收拼接后数组

    // 接在后面
    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    // 将 arr2 中所有元素附加到 arr1 后面并返回
    var arr3 = arr1.concat(arr2);
    
    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    var arr3 = [...arr1, ...arr2];
    
    // 插在前面
    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    // 将 arr2 中的元素插入到 arr1 的开头
    Array.prototype.unshift.apply(arr1, arr2) // arr1 现在是 [3, 4, 5, 0, 1, 2]
    
    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    arr1 = [...arr2, ...arr1]; // arr1 现在为 [3, 4, 5, 0, 1, 2]
    

    构造对象的展开语法

    将已有对象的所有可枚举属性拷贝到新构造的对象中

    对象的拷贝

    var obj1 = { foo: 'bar', x: 42 };
    var obj2 = { foo: 'baz', y: 13 };
    
    var clonedObj = { ...obj1 };
    // 克隆后的对象: { foo: "bar", x: 42 }
    
    var mergedObj = { ...obj1, ...obj2 };
    // 合并后的对象: { foo: "baz", x: 42, y: 13 }
    

    MDN

    解构赋值

    mdn

    • 字面量的语法方式为定义某个数据组提供了极大的便利,解构赋值使用的相同的语法,左值和右值,但有多出左值可以从右边的变量中取出需要的值
    var x = [1, 2, 3, 4, 5];
    var [y, z] = x;
    console.log(y); // 1
    console.log(z); // 2
    

    解构数组

    • 见下面的例子,当你在声明变量时就将其放置在左边的一个[ ]里,里面的变量可以获取到右边的数组里的对应位置的值
    var foo = ["one", "two", "three"];
        
    var [one, two, three] = foo;
    console.log(one); // "one"
    console.log(two); // "two"
    console.log(three); // "three"
    
    • 并不是一定需要在定义时就对其进行赋值,已声明的变量依然可以用这种方式赋值
    var a, b;
    [a, b] = [1, 2];
    console.log(a); // 1
    console.log(b); // 2
    
    • 可以为其设置默认值,以防止出现值未定义(undefined)的情况
    var a, b;
    
    [a=5, b=7] = [1];
    console.log(a); // 1
    console.log(b); // 7
    
    • 由于解构赋值的特性,交换变量也有了简易方法,下面的a,b时已声明且赋值的变量,解构赋值语法让它们可以通过将变量组合一个数组放置右边,左边将其位置调换以此来获得交换的值
    var a = 1;
    var b = 3;
    
    [a, b] = [b, a];
    console.log(a); // 3
    console.log(b); // 1
    
    • 解构一个从函数返回的数组,当函数使用数组作为参数时使用了展开运算符
    function f() {
      return [1, 2];
    }
    
    var a, b; 
    [a, b] = f(); 
    console.log(a); // 1
    console.log(b); // 2
    
    //忽略某些返回值
    var [a, , b] = f();
    console.log(a); // 1
    console.log(b); // 3
    
    • 只接受数组中部分值,剩余部分赋值给变量作为一个新数组,剩余元素(可以类比剩余参数)必须是数组的左右一项
    var [a, ...b] = [1, 2, 3];
    console.log(a); // 1
    console.log(b); // [2, 3]
    
    • 用正则表达式匹配提取值
      用正则表达式方法exec()匹配字符串会返回一个数组,该数组第一个值是完全匹配正则表达式的字符串,然后的值是匹配正则表达式括号内内容部分。解构赋值允许你轻易地提取出需要的部分,忽略完全匹配的字符串——如果不需要的话。
    var url = "https://developer.mozilla.org/en-US/Web/JavaScript";
    
    var parsedURL = /^(w+)://([^/]+)/(.*)$/.exec(url);
    console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]
    
    var [, protocol, fullhost, fullpath] = parsedURL;
    
    console.log(protocol); // "https"
    

    解构对象

    • 赋值
    var o = {p: 42, q: true};
    var {p, q} = o;
    
    console.log(p); // 42
    console.log(q); // true
    
    //无声明赋值
    //通过解构可以无需声明来赋值一个变量
    
    var a, b;
    
    ({a, b} = {a: 1, b: 2}); // 此处使用小括号包裹让其对象字面量
    
    • 赋值给新的变量名, 左边的 { }不代表它是一个对象,而这是结构赋值的语法,左边{}的依然是独立的变量,上面的数组也是同理,赋值给一个与属性名不同的变量名时需要将属性与变量进行“绑定”.上面的相同的情况则无需如此
    var o = {p: 42, q: true};
    var {p: foo, q: bar} = o;
     
    console.log(foo); // 42 
    console.log(bar); // true
    
    
    • 给变量事先设定默认值,当属性不存在时变量就会使用默认值
    var {a = 10, b = 5} = {a: 3};
    console.log(a); // 3
    console.log(b); // 5
    
    // 新变量的默认值
    var {a:aa = 10, b:bb = 5} = {a: 3};
    console.log(aa); // 3
    console.log(bb); // 5
    

    函数参数的解构赋值

    函数参数是一个数组时,它会将其拆分为变量来执行,当是对象时如下:

    function ({a=1,b=3} = {}){ ... }
    // 这里后面的空对象的作用下文有提到
    // 就是让其在不传参数时也可以被调用
    // 这个式子在没有传递参数和传递参数为空对象时a,b均可使用,因为它有默认值
    
    function ({a,b} = {a:1,b:2}){ ... }
    // 这里的a,b是没有默认值的,
    // 你在没有传递参数时会调用后面这个默认参数,
    // 而当你传递空对象时也就不会调用它,
    // 所以这时使用a,b将都是undefined
    

    MDN上这个例子非常好的诠释了结构赋值的用法和精髓

    // ES5
    function drawES5Chart(options) {
      options = options === undefined ? {} : options;
      var size = options.size === undefined ? 'big' : options.size;
      var cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords;
      var radius = options.radius === undefined ? 25 : options.radius;
      console.log(size, cords, radius);
      // now finally do some chart drawing
    }
    
    drawES5Chart({
      cords: { x: 18, y: 30 },
      radius: 30
    });
    

    在es5时,函数参数在为其设置默认值时,参数存放在对象里并检测每个值是否存在并且为其设置默认值,而在es6中使用解构赋值非常方便的,接收到对象参数后可以轻松将其赋给对应的形参以便使用

    // ES6
    function drawES2015Chart({size = 'big', cords = { x: 0, y: 0 }, radius = 25} = {}) 
    {
      console.log(size, cords, radius);
      // do some chart drawing
    }
    
    drawES2015Chart({
      cords: { x: 18, y: 30 },
      radius: 30
    });
    

    在参数里为其设置一个空对象时因为这样的话可以在不提供参数的情况下直接使用函数,如果不提供让你提供至少一个参数

    解构嵌套对象和数组

    嵌套数组

    var metadata = {
        title: "Scratchpad",
        translations: [
           {
            locale: "de",
            localization_tags: [ ],
            last_edit: "2014-04-14T08:43:37",
            url: "/de/docs/Tools/Scratchpad",
            title: "JavaScript-Umgebung"
           }
        ],
        url: "/en-US/docs/Tools/Scratchpad"
    };
    
    var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata;
    
    console.log(englishTitle); // "Scratchpad"
    console.log(localeTitle);  // "JavaScript-Umgebung"
    

    var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata; 这里首先是不同于属性的变量名赋值,然后嵌套的 translations里查找为 title的属性赋值给新变量 localeTitle

    嵌套对象

    var obj ={
        name: "lee",
        family: {
            son: "kangkang",
            girl: "jane"
        }
    }
    
    var {name, family: {girl:daughter}} = obj
    

    迭代

    var people = [
      {
        name: "Mike Smith",
        family: {
          mother: "Jane Smith",
          father: "Harry Smith",
          sister: "Samantha Smith"
        },
        age: 35
      },
      {
        name: "Tom Jones",
        family: {
          mother: "Norah Jones",
          father: "Richard Jones",
          brother: "Howard Jones"
        },
        age: 25
      }
    ];
    
    for (var {name: n, family: { father: f } } of people) {
      console.log("Name: " + n + ", Father: " + f);
    }
    
    // "Name: Mike Smith, Father: Harry Smith"
    // "Name: Tom Jones, Father: Richard Jones"
    

    剩余参数

    与展开语法相反的是剩余参数是将不定数量的参数(形式参数)表示为一个数组,接收的参数多余已经给定的形式参数时多余的将放入其中,它是一个数组,具有数组所具有的功能

    • 语法:放在最后且除了给与形参的参数外均合并放在数组里
    function(a, b, ...theArgs) {
      // ...
    }
    

    示例

    function sum(...theArgs) {
      return theArgs.reduce((previous, current) => {
        return previous + current;
      });
    }
    
    console.log(sum(1, 2, 3));
    // expected output: 6
    
    console.log(sum(1, 2, 3, 4));
    // expected output: 10
    

    剩余参数和 arguments对象的区别

    剩余参数和 arguments对象之间的区别主要有三个:

    1. 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
    2. arguments对象不是一个真正的数组,而剩余参数是真正的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach或pop。
      arguments对象还有一些附加的属性 (如callee属性)

    全文摘自MDN,具体详细正确请参考MDN

    (∩_∩)-----代码改变生活。
  • 相关阅读:
    OS-TEP: Fetch-And-Add
    ULK --- Chap 4: Tasklets (Note)
    ULK --- Chap 4: ksoftirqd kernel threads (Note)
    ULK --- Chap 4: Softirqs and Tasklets (Note)
    ULK --- Chap 4: Nested Execution of Exception and Interrupt Handlers
    ULK --- Chap 4: Interrupt Descriptor Table
    己所欲,勿施于人 --- 周国平
    善良 丰富 高贵 --- 周国平
    第一重要的是做人 --- 周国平
    Operating System: Three Easy Pieces --- Load-Linked and Store-Conditional (Note)
  • 原文地址:https://www.cnblogs.com/daixixi/p/9314653.html
Copyright © 2011-2022 走看看