ES6新特性小结

ES6新特性

1.let 和 const

     /* 
        1.let var const 变量
        const一般在require一个模块的时候用或者定义一些全局常量。
        let 变量,块作用域,不能重复声明覆盖
        var 变量,函数作用域,能重复声明覆盖
      */
     aaa2(){
        this.bb();
       const a=2;
       a=3;
       console.log(a,"11111");
       /* 
         TypeError: Assignment to constant variable.
       */
     },
      bb(){
        var a=[1,2];
        for(let i=0;i<a.length;i++){
           console.log(i,"111");
        }
        console.log(i, "222");
        for (var i = 0; i < a.length; i++) {
          console.log(i, "333");
        }
        console.log(i, "444");
        /* 
          0 "111"
          1 "111"
          undefined "222"
          0 "333"
          1 "333"
          2 "444"
        */
      },

2.变量的解构赋值

1.数组的解构赋值

 b1(){
            // 1.前后模式匹配
            var [a,b,c]=[1,3,6];
            console.log(a,b,c);  // 1 3 6
            var [a,[b,[[c]]]]=[1,[2,[[4]]]];
            console.log(a, b, c); // 1 2 4

            // 2.前多后少
            var [a,b,c]=[2,3];
            console.log(a, b, c); // 2 3 undefined
            var [[a,[b]],c]=[[1,[]],4];
            console.log(a, b, c);  // 1 undefined 4

            // 3.前少后多
            var [a,b] = [2,3,1];
            console.log(a, b); // 2 3
            var [,,c]=[2,3,1];
            console.log(c); // 1
            var [...a]=[2,3,1];
            console.log(a);  //  [2, 3, 1]

            // *** 解构时,如果等号右边是不可遍历的,则会报错 *****
            // var [a, b] = 1;
            // var [a, b] = null;
            // var [a, b] = {};
            // var [a,b]=true;
            // var [a,b]=NaN;
            // var [a, b] = undefined;
            // console.log(a); // TypeError: X is not iterable

            // 4.带默认值 
            // 先结构赋值,没有值的话再使用默认值
            var [a=3,b,c]=[1,2,3];
            console.log(a,b,c); // 1 2 3
            var [a = 3, b, c] = [, 2, 3];
            console.log(a,b,c);  // 3 2 3
          },

2.对象的解构赋值

 b2(){
            var {a,b}={b:1};
            console.log(a, b, "2222222222");  // undefined 1 "2222222222"
            var { a: name, b: value } = { a: 1, b: 2 };
            console.log(name, value)      // 1 2
            var {a:name,b:value}=[1,2];
            console.log(name, value, "111111111")   // undefined undefined "111111111"
            var {0:name,1:value} = [1,2]; // 数组是一个特殊的对象  [1,2] 效果等同于 {0:1,1:2}
            console.log(name, value);          // 1 2
            // 通过解构,我们可以很容易的把对象的方法复制给变量。
            const {log} = console;
            log("aaaaa");      // aaaaa
            const {log:name1} = console;
            name1("name");      // name
          },

3.字符串的解构赋值

 // 因为字符串具有length这个属性,因此我们还可以对该属性进行解构赋值:
          b3(){
            const [a,b,c,d,e,f]="future";
            console.log(a, b, c, d, e, f);    // f u t u r e
            let {length:aa}="future";
            console.log(aa)                   // 6
          },

4.数字以及布尔值的解构赋值

 // 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象,
          // 但是等号右边为undefined 和 null时无法转为对象,所以对他们进行解构赋值时,都会报错
          b4(){
            let {toString:s}=123;
            console.log(s);        // ƒ toString() { [native code] }
            // let { prop: x } = null;
            // console.log(x);       // TypeError: Cannot destructure property 'prop' of 'null' as it is null.
          }, 

5.函数参数的解构赋值

 b5(){
            function aa([a,b,c]) {
              return a+b-c;
            };
            console.log(aa([2,3,1]),"434");

            function bb([a, b, c]=[2,3,0]) {
              return a + b - c;
            };
            console.log(bb([5, 4, 2]));     // 7
            console.log(bb([5, 4]));        // NaN
            console.log(bb([]));            // NaN
            console.log(bb());              // 5

            function cc({x,y}={x:3,y:5}) {
              return x+y;
            }
            console.log(cc({ x: 4, y: 6 })); // 10
            console.log(cc({ x: 4 }));      // NaN
            console.log(cc({}));            // NaN 
            console.log(cc());              // 8

            function dd({ x=3,y=6 }) {
              return x + y;
            }
            console.log(dd({ x: 4, y: 7 })); // 11
            console.log(dd({ x: 4 }));      // 10
            console.log(dd({}));            // 9 
            // console.log(dd());              // TypeError: Cannot read property 'x' of undefined
          },

6.解构的用途

b6(){
            // 1.交换变量的值
            function aa(x,y) {
              [x,y]=[y,x];
              console.log(x,y);
            };
            aa(5, 7);    // 7 5

            // 2.函数只能返回一个值,如果想返回多个值,需要将它们放在数组或对象里返回
            function bb() {
              return {a:1,b:2}
            }
            let {a,b}=bb();
            console.log(a,b);

            // 3.函数参数的定义
            //参数是一组有次序的值
            function cc([x, y, z]) {
              return x + y + z;
            }
            cc([2,3,5])
            console.log(cc([2,3,5])); // 10
            //参数是一组无次序的值
            function f({ x, y, z }) {
              return x + y + z;
            }
            f({ x: 'a', z: 'b', y: 'c' });
            console.log(f({ x: 'a', z: 'b', y: 'c' })); // acb
            // 4.提取json数据
            // 5.函数参数的默认值
            // 6.输入模块的指定用法

          },

3.模板字符串

    如下:
    使用 `` 符号括起来,使用${变量名},
    可以使用${方法名}调用函数,
    可以直接写表达式,${a+b},输出a+b的结果;
aaa(){
        console.log("here is my number:" + this.number + " my name is:" + this.name, "65656565");
        alert(`${this.bbb()}`); // 可以调用aaa1();
        this.bbb();
         /* output: 
            here is my number:undefinedmy name is:gfjgif 65656565
         */
      },
      bbb() {
        var a=1,b=3;
        console.log(`here is my number:${this.number} my name is:${this.name}`, "2332323",`${a+b}`);

        /* output:
           here is my number:12345678901 my name is:gfjgif 2332323 4
        */
      },

4.箭头函数

使用 => 来定义函数
函数表达式 函数声明
不带参 var a = ()=>{} a(()=>{})
带参 var a = val =>{} a(val=>{})

aaa3(){
          // 1>.带参数
          var a = val=>console.log(val);
          a("string");
          var a = (g,h)=>g+h;
          console.log(a(4,3));   // 7
          // 2>.不带参数
          var a=()=>{
            console.log("aaa");
          };
      },

5.Symbol

ES6引入一种新的原始数据类型为 Symbol ,表示为 独一无二 的值,用来定义独一无二的对象属性名。

      aaa4(){
        let a = Symbol("abc");
        let b = Symbol("abc");
        let c = Symbol();
        console.log(a, b, c, a == b, typeof a);  // Symbol(abc) Symbol(abc) Symbol() false "symbol"
        }

1.消除魔术字符串(当常量多的时候我们就要去给他们赋值很多的唯一值很麻烦)

  symbolTest(){
            // bad
            const aaType = "abc";
            const bbType = "bcd";
            const ccType = "cde";
            // nice
            const aType = Symbol();
            const bType = Symbol();
            const cType = Symbol();
            // switch(type){
            //   case aType:
            //      break;
            //   case bType:
            //      break;
            //   case cType:
            //      break;
            // }
            }

** Symbol的值作为对象属性名,是不能用点运算符的。

2.Symbol作为对象属性名

            // 1>.
            let symbol = Symbol();
            let symbol1 = Symbol();
            let a1 = {};
            a1.symbol = "qwer";
            a1[symbol] = "asd";   
            a1[symbol1] = "fff";
            console.log(a1, a1[symbol], a1[symbol1],a1.symbol) 
            // {symbol: "qwer", Symbol(): "asd", Symbol(): "fff"} "asd" "fff" "qwer"

            // 2>.
            a1={
              [symbol]:'df',
            };
            console.log(a1, "21");    // {Symbol(): "df"} "21"
            
            // 3>.
            let a2={};
            Object.defineProperty(a2, symbol, { value: 'web' });
            console.log(a2);      // {Symbol(): "web"}

            /* 

3.Symbol for

这个东西是可共享,在创建的时候会检查全局是否寻在这个key的symbol.
如果存在就直接返回这个symbol, 如果不存在就会创建,并且在全局注册。

 let key = Symbol("name");
            let key2 = Symbol("name");
            let key3 = Symbol.for("name");
            let key4 = Symbol.for("name");
            console.log(key === key2, key3 === key4);  // false true

4.Symbol keyFor

如果全局注册表中查找到该symbol,则返回该symbol的key值,形式为string。
如果symbol未在注册表中,返回undefined;

 let hh = Symbol();
            Symbol.keyFor(hh);
            let hh1 = Symbol.for("asd");
            Symbol.keyFor(hh1);
            console.log(hh1, Symbol.keyFor(hh), Symbol.keyFor(hh1));  // undefined "asd"

6.Set和Map

set(集合):它类似于数组,但是成员的值都是唯一的,没有重复的值;
Map(字典):字典是以[键,值]的形式存储,键值对;

1.Set

 let arry=[6,"aaa","e","aaa",5,4,5,6];
         let arry1=new Set(arry);
         let a=[...arry1];
         console.log([...new Set(arry)],arry1,a); 
         // (7) [6, "aaa", "e", 5, 4] Set(7) {6, "aaa", "e", 5, 4} (7) [6, "aaa", "e", 5, 4]
         
         const b = new Set();
         [1,5,4,7,6,7,5,4].forEach(val=>b.add(val));
         console.log(b, [...b]);    // Set(5) {1, 5, 4, 7, 6} (5) [1, 5, 4, 7, 6]

         const c = new Set([2,3,2,4,5,1,3,4]);
         console.log([...c]);       // (5) [2, 3, 4, 5, 1]

         // 去重字符串
         console.log([...new Set("asdffsadsfsfg")]);    // (5) ["a", "s", "d", "f", "g"]
         console.log([...new Set("asdffsadsfsfg")].join(""));   // asdfg

         // Array.from方法可以将 Set 结构转为数组。
         console.log(arry1, Array.from(arry1));    
         // Set(5) {6, "aaa", "e", 5, 4} (5) [6, "aaa", "e", 5, 4]

Set 结构的实例有四个遍历方法,可以用于遍历成员。
Set.prototype.keys():返回键名的遍历器
Set.prototype.values():返回键值的遍历器
Set.prototype.entries():返回键值对的遍历器
Set.prototype.forEach():使用回调函数遍历每个成员

let d = [2,4,6,5,3,2,4,6];
          d = new Set([...d].filter(val=>(val%3==0)));
          console.log([...d]);         // (2) [6, 3]    

          // 交集,并集,差集
          let e = new Set([3, 5, 9, 7, 5, 1]), f = new Set([2, 4, 6, 5, 3, 2, 4, 6]);
          let h = new Set([...e,...f]);
          let g = new Set([...e].filter(val => f.has(val)));
          let i = new Set([...e].filter(val => !f.has(val)));
          console.log(g, h, i);      
          // Set(2) {3, 5} Set(8) {3, 5, 9, 7, 1, 2, 4, 6} Set(3) {9, 7, 1}

2.WeakSet 也是不重复的值得集合,它的成员只能是对象,而不能是其他类型的值, WeakSet 没有size属性,没有办法遍历它的成员。

  const k = [1, 2];
           const j = [[1,1],[1,2]];
           console.log(new WeakSet(j));      // WeakSet {Array(2), Array(2)}
          //  console.log(new WeakSet(k));      // Invalid value used in weak set

3. 共有的方法:delete删除,has有无,clear清空。对于Set的添加操作是add(), 而Map是set设置和get获取。

4. map

const l = new Map();
               l.set("name","tom");
               console.log(l.get("name"));         // tom
               console.log(l.delete("name"));      // true
               console.log(l.size);                // 0
 /* 
            map 对条件语句的优化
              switch(type){
                case 'A':
                  return a;
                  break;
                case 'B':
                  return b;
                  break;
                default:
                  return c;
                  break;
              }
            */
           const cond=new Map().set("A","a").set("B","b");
           function getName(val) {
              return cond.get(val) || "c";
           }
           console.log(getName("A"))      // a

Map 结构原生提供三个遍历器生成函数和一个遍历方法。
Map.prototype.keys():返回键名的遍历器。
Map.prototype.values():返回键值的遍历器。
Map.prototype.entries():返回所有成员的遍历器。
Map.prototype.forEach():遍历 Map 的所有成员。

 const map = new Map()
            .set(1,"a")
            .set(2,"s")
            .set(3,"d");
            console.log([...map.values()]);       // ["a", "s", "d"]
            console.log([...map.keys()]);         // (3) [1, 2, 3]
            console.log(...map.entries());        // (2) [1, "a"] (2) [2, "s"] (2) [3, "d"]
            console.log([...map].filter(([k, v]) => k > 2));   // (2) [3, "d"]

5. WeakMap

WeakMap结构与Map结构类似,也是用于生成键值对的集合;
WeakMap只接受对象作为键名(null除外),不接受其他类型的值作为键名;
WeakMap的键名所指向的对象,不计入垃圾回收机制.

7.for of

遍历:数组,Set,Map,类数组对象,如 arguments 对象、DOM NodeList 对象,Generator 对象,字符串
item 当前元素

aaa6() {
         let a=[4,3,6];
        for (item of a){
            console.log(item);      // 4 3 6
         };
        let a1 = [4, 3, 6];
        for (item of a1.entries()) {
          console.log(item);      
          // (2)[0, 4]
          // (2)[1, 3]
          // (2)[2, 6]
        }
      },

8.Promise

Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,
原型上有then、catch等方法;
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),
在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从
“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,
作为参数传递出去。相当于resolve是对promise成功时候的回调,它把promise的状态修改为fullfiled,
那么,reject就是失败的时候的回调,他把promise的状态修改为rejected,
1.Promise 是异步编程的一种解决方案
有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)

function loadImageAsync(url) {
  return new Promise(function(resolve, reject) {
    const image = new Image();
    //  成功
    image.onload = function() {
      resolve(image);
    };
    //  失败
    image.onerror = function() {
      reject(new Error('Could not load image at ' + url));
    };

    image.src = url;
  });
}

2.then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // ...
});

3.finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
4.Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
5.Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。(那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。)
6.Promise.allSettled()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。
只有等到所有这些参数实例都返回结果,不管是fulfilled还是rejected,包装实例才会结束。
7.Promise.any()方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。(全部失败才会失败,有一个成功就会成功)
Promise.any()跟Promise.race()方法很像,只有一点不同,就是不会因为某个 Promise 变成rejected状态而结束。

const promise = new Promise(function(resolve, reject) {
          // ... some code
          if ( //异步操作成功 ) {
          resolve(value);
        } else {
          reject(error);
        }
        });

        promise.then(function(value) {
            // success
          }, function(error) {
            // failure
          });
      */
      aaa7() {
        /*
        定时5秒内如果请求数据失败就重新发起请求;
        如果请求成功就OK
        */
        var time = Math.floor(Math.random() * 10000);
        //请求某个table数据
        function requestTableList() {
          var p = new Promise((resolve, reject) => {
            //去后台请求数据,这里可以是ajax,可以是axios,可以是fetch 
            setTimeout(() => {
              let res = [{ a: 1, b: 2, c: 3 }];
              resolve(res);
            }, time);
          });
          return p;
        }
        // 控制请求时间如果超过5秒就直接结束
        //延时函数,用于给请求计时 5s
        function timeout() {
          var p = new Promise((resolve, reject) => {
            setTimeout(() => {
              reject('请求超时');
            }, 5000);
          });
          return p;
        }
        Promise.race([requestTableList(), timeout()]).then((data) => {
          //进行成功回调处理
          console.log(data);
        }).catch((err) => {
          // 失败回调处理
          console.log(err);
          this.aaa7();
        }).finally(()=>{
          console.log("closed")
        });

        // finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
        var p=new Promise((resolve,reject)=>{

        })
          .then(result => {/*  ···  */})
          .catch(error => {/*  ···  */})
          .finally(() => {/*  ···  */});
       
      },

9.Async

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,
一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

// 基本用法:
function timeout(ms) {
              return new Promise((resolve) => {
                setTimeout(resolve, ms);
              });
            }

            async function asyncPrint(value, ms) {
              await timeout(ms);
              console.log(value);
            }

            asyncPrint('hello world', 5000);
          },
/* 
        错误处理:
        如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。
       */
        async function f() {
          try {
            await new Promise(function (resolve, reject) {
              throw new Error('出错了');
            });
          } catch (e) {
          }
          return await ('hello world');
        }
        // 如果有多个await命令,可以统一放在try...catch结构中。

        async function main() {
          try {
            const val1 = await firstStep();
            const val2 = await secondStep(val1);
            const val3 = await thirdStep(val1, val2);

            console.log('Final: ', val3);
          }
          catch (err) {
            console.error(err);
          }
        }

10.Class

1.定义和属性

 aaa9() {
         class Hh{
            constructor(x,y){
              this.x = x;
              this.y = y;
            };
            sum(a,b) { 
                console.log(this.x,this.y);     // 10 5
                return a+b+this.x+this.y;
            };
            //  类的方法内部如果含有this,它默认指向类的实例。
            //  注意,如果静态方法包含this关键字,这个this指的是类,而不是实例。
            static say(){
              return "ddddddd"
            };
            say1() {
              return (this.x + "*******88");  // 10*******88
            }
         }

         // name属性总是返回紧跟在class后面的类名;
         console.log(Hh.name);  // Hh

         // 类的数据类型就是函数,类本身就指向构造函数。
        console.log(typeof (Hh), Hh === Hh.prototype.constructor);  // function true

        let a=new Hh(10,5);
        console.log();
        console.log(a.sum(5, 10), a.say1());   // 30 "10*******88"

        // 类的所有方法都定义在类的prototype属性上面。
        console.log(Hh.prototype);
        /* {constructor: ƒ, sum: ƒ, say1: ƒ} */
        // 在类的实例上面调用方法,其实就是调用原型上的方法
        console.log(a.constructor === Hh.prototype.constructor);     // true

        /* 
         constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,
         如果没有显式定义,一个空的constructor方法会被默认添加。
        */
       },

2.class表达式

class1(){
           /*  
             这个类的名字是P,但是P只在 Class 的内部可用,指代当前类。
             在 Class 外部,这个类只能用user引用。 
           */
          const user = class P {
            sayHello() {
              return P.name;
            }
          };
          let a = new user();
          console.log(a.sayHello())      // P 
          // console.log(P.name);        // ReferenceError: P is not defined  

          /* 
            采用Class表达式,可以写出立即执行的Class。
          */
          const user1 = new class {
            constructor(name){
              this.name = name;
            };
            sayHello() {
              return `Hello ${this.name}`;
            }
          }("飞蛾");
          console.log(user1.sayHello());
        },

3.静态方法 / 静态属性

1.静态方法

          class Hh{
            static say() {
              return "ddddddd";
            };
            say1() {
              return (this.x + "*******88");  // 10*******88
            }
          }
          let a = new Hh(10, 5);
          // 类的静态方法(static)不会被实例继承
          // console.log(Hh.say1());    // Hh.say1 is not a function
          console.log(Hh.say());     // ddddddd 
          // console.log(a.say());      // TypeError: a.say is not a function

          // 子类可以调用父类的静态方法
          class Hh1 extends Hh {

            // 静态方法也是可以从super对象上调用的。
            static say() {
              return super.say() + "123";
            }
          };
          console.log(Hh1.say(), Hh1.say());   // ddddddd ddddddd123

1.静态属性

定义了 a 的一个静态属性prop

// 老写法
           class A{ }
             a.prop=3;
           // 新写法
           class B{
             static prop = 3;
           }
          },

4.class 的继承

在 constructor 中必须调用 super 方法,因为子类没有自己的 this 对象,而是继承父类的
this 对象,然后对其进行加工,而 super 就代表了父类的构造函数。super 虽然代表了父类 A 的
构造函数,但是返回的是子类 B 的实例,即 super 内部的 this 指的是 B.
在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例
的构建,基于父类实例,只有super方法才能调用父类实例。

class A {
              sayHi(){
                return "Hi"
              }
            }
            class B extends A {
              constructor(x,y,a){
                super();
                 this.a=a;
              };
              sayHi(){
                 return this.a+""+super.sayHi();    // super 作为对象可以调用父类的方法
              }
            }
            let c=new B(1,2,3); 
            console.log(c.sayHi());        // 3Hi  

            

如果子类没有定义constructor方法,这个方法会被默认添加

 //  class C extends A { }
             // 相当于
             class C extends A {
               constructor(...val){
                 super(...val);
               }
              }

Object.getPrototypeOf() 得出一个子类的父类

console.log(Object.getPrototypeOf(C)=== A)   // true

由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

 class A1{
              constructor(){
                this.a=1;
                A1.prototype.b=2;
              }
            }
            class B1 extends A1 {
               getData(){
                  return super.a;
               };
              getData1() {
                return super.b;
              }
            }
            let bb = new B1();
            console.log(bb.getData());     // undefined
            console.log(bb.getData1());    // 2

在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例。

class A2{
              constructor(){
                this.a=1;
              };
              static sayHi(){
                 console.log("12345")
              }
            };
            class B2 extends A2{
              constructor(){
                super();
                this.a=2;
              };
              static sayHi(){
                super.sayHi();
              }
            }
            let b2 = new B2();
              console.log(b2.a);   // 2
              B2.a;           //  2
              // b2.sayHi();     //  TypeError: b2.sayHi is not a function      
              B2.sayHi();     // 12345 

子类的__proto__属性,表示构造函数的继承,总是指向父类。
子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

 class A3 { };
               class B3 extends A3 { };
               console.log(B3.__proto__ === A3, B3.prototype.__proto__ === A3.prototype); // true true

子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,
子类的原型的原型,是父类的原型。

 let a3 = new A3(); 
               let b3 = new B3();
               console.log(b3.__proto__.__proto__ === a3.__proto__);  // true

11.Decorator类装饰器

// 需要配置jsconfig.json
        {
            "compilerOptions": {
               "experimentalDecorators": true,
            }
        }
      aaa10() {
        //  @ok
        //  class A { }
        //  function ok(S){
        //     S.isOk="ok";
        //  };
        //  A.isOk;
        
      },

12.扩展运算符

1. …运算符

1.对于数组

1.数组拼接
 let a1 = [1, 2], b1 = [3, 4], c1 = [5, 6];
        let a2 = [...a1, ...b1, ...c1];
        console.log(a2)     // (6) [1, 2, 3, 4, 5, 6]

2.将数组转换为元素序列
 let b2 = [2, 3, 4, 5];
        console.log(b1, ...b1);  // [3, 4] 3 4

3.拷贝数组(深拷贝)
 let b3 = [3, 4, 5];
        let c2 = [...b3];
        c2[0] = 9;
        console.log(c2, b3, ...b3);   // (3) [9, 4, 5] (3) [3, 4, 5] 3 4 5
4.将字符串转化为数组
 let str = "zzxkdndnv";
        let arr = [...str];
        console.log(arr);      // (9) ["z", "z", "x", "k", "d", "n", "d", "n", "v"]
5. 拆分数组…last 必须要放到最后面
let [first, second, ...last] = [1, 3, 4, 5, 6, 8];
        console.log(first, second, last);    // 1 3 (4) [4, 5, 6, 8]
        //  let [first1, ...last1, second1] = [1, 3, 4, 5, 6, 8];
        //  console.log(first1, last1, second1);  // Uncaught SyntaxError: Rest element must be last element
        //  let [...last2, second2] = [1, 3, 4, 5, 6, 8];
        //  console.log(last2, second2);         // Uncaught SyntaxError: Rest element must be last element

2.对于对象

1.对象的拷贝
let obj = { a: 1, b: 2 };
        let obj1 = { ...obj };
        console.log(obj1);     // {a: 1, b: 2}
2.对象的修改
 let obj2 = { a: 1, b: 2 }; 
        let obj3 = { ...obj, a: 5, b: 6 };
        let obj4 = { ...obj, b: 9 };
        let obj5 = { ...obj, ...{ a: 7, b: 8 } };
        console.log(obj2, obj3, obj4, obj5);    // {a: 1, b: 2} {a: 5, b: 6} {a: 1, b: 9} {a: 7, b: 8}

13.数组的扩展

aaa12(){
         let x=3;
         const arr = [
          ...(x > 0 ? ['a'] : []),
          'b',
        ];
        console.log(arr, "434343");     // (2) ["a", "b"] "434343"

        // 替代函数的apply方法
        function sum(a,b,c){
           return a+b+c;
        };
        let k = [1,2,3];
        // ES5
        console.log(sum.apply(null,k));          // 6
        console.log(Math.max(k));                // NaN
        console.log(Math.max.apply(null,k))      // 3
        // ES6
        console.log(sum(...k));                  // 6
        console.log(Math.max(...k));             // 3

1.Array.from

1.用于将对象转为正真的数组

let a = {
          0: "a",
          1: "b",
          length:2
        };
        console.log(Array.from("dsd457g"));       // (7) ["d", "s", "d", "4", "5", "7", "g"] 
        console.log(Array.from(a));               // (2) ["a", "b"]

2.Array.from 还可以接受第二个参数,用于对数组的元素进行操作

let b =[5,3,9,4];
             let c = Array.from(b,x=>x*2);
             console.log(c);           // (4) [10, 6, 18, 8]
             let d = [0,1,,2,,,3];
             let e = Array.from(d, x => x || 0);
             console.log(e);           // (7) [0, 1, 0, 2, 0, 0, 3]

2.Array.of

1.用于将一组值转为数组

 console.log(Array.of(1, 23, 6, 4));      // (4) [1, 23, 6, 4]
            console.log(Array.of(1, 23, 6, 4).length);      // 4

3.copyWithin

数组实例的 copyWithin()
它接受三个参数。
target (必需):从该位置开始替换数据(位置从0开始)。
start (可选):从该位置开始读取数据,默认为 0 。如果为负值,表示倒数。
end (可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

 /* 
            从数组下标为1的地方开始替换(a[1]);
            要替换的数的开始;
            要替换的数的结束(不包含这个元素);
            copyWithin(1,2,5)表示,复制数组a[2]到a[4]的元素,从a[1]开始往后替换
          */
          console.log([1, 2, 3, 4, 5, 6, 7].copyWithin(1, 2, 5));     // (7) [1, 3, 4, 5, 5, 6, 7] 

4.find和findIndex

find():
三个参数:1.当前元素;2.当前元素下标;3.原数组
找到一个符合条件的就返回,没有符合条件的就返回undefined
findIndex():
和find()一样,也有三个参数,它返回的是符合条件的元素的下标
如果都不符合条件就返回-1;

 let arr1 = [2, 3, 4, 5, 6].find(x => x > 2);
            let arr2 = [2,3,4,5,6].find(function(value,index,arry){
              return value>4
            })
            console.log(arr1,arr2)     // 3 5

            // find函数接收了第二个参数person对象,回调函数中的this对象指向person对象。
            let person={"name":"sb","age":24};
            function aaa(x){
               return   x>this.age
            }
            let arr3 = [21, 19, 34, 26].find(aaa,person);
            console.log(arr3);          // 34

5.fill

fill()
fill 用于填充数组
三个参数:
1.用于填充的元素;(必须)
2.需要替换的元素的下标起始位置;(可选)
3.需要替换的元素下标的截止位置;(不包含此元素)(可选)

 console.log([1, 2, 3].fill(4));               // (3) [4, 4, 4]
            console.log([1, 2, 3, 5, 8].fill(4, 2, 4));         // (5) [1, 2, 4, 4, 8]

6.entries,keys,values

唯一的区别是keys()是对键名的遍历
values()是对键值的遍历
entries()是对键值对的遍历

 for( i of ["a","s","d"].keys()){
                console.log(i)                // 0 1 2 
             }
              for ( i of ["a", "s", "d"].values()) {
                console.log(i)                // a s d
             }
              for ( i of ["a", "s", "d"].entries()) {
                console.log(i)               
             }
             /* 
               (2) [0, "a"]
               (2) [1, "s"]
               (2) [2, "d"]
             */

7.includes

两个参数:
1.需要搜索的元素(必须)
2.搜索的起始位置(可选),默认为0;如果为负数,则表示倒数的位置,如果负数的绝对值大等于数组的长度,则为0;

 console.log([2, 3, 7, 4].includes(2));        // true
 console.log([2,3,7,4].includes(2,1));       // false

8.flat和flatMap

flat():将嵌套的数组拉平,变为一维数组
参数:默认为1:意为拉平一层,要想拉平几层就填几
flatMap():此方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),
然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。

 console.log([1, [2, 4, 6], 7].flat());            // (5) [1, 2, 4, 6, 7]
                console.log([1, [2, [3, 4], 6], 7].flat(2));      // (6) [1, 2, 3, 4, 6, 7]
 // 如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
                console.log([1, [2, [3, [4, [8]]], 6], 7].flat(Infinity));  //(7) [1, 2, 3, 4, 8, 6, 7]
                
                // 去空元素
                console.log([1, , 3, 4, , 7].flat());     // (4) [1, 3, 4, 7]

                // flatMap 操作数组元素
                console.log([1, 3, 5].flatMap(x => x * 2));        // (3) [2, 6, 10]
                console.log([1, 3, 5].flatMap(x => [x, x * 2]));   // (6) [1, 2, 3, 6, 5, 10]
               

9.数组的空位

forEach(), filter(), reduce(), every() 和some()都会跳过空位。
map()会跳过空位,但会保留这个值
join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。
Array.from,(…),entries(),keys(),values(),find()和findIndex()会将空位处理成undefined。

猜你喜欢

转载自blog.csdn.net/yang__k/article/details/106388724