ES6学习的个人总结

   博客仅用来记录自己的学习历程,如果有错,希望您能私信我,或者在评论区提出,感谢

1.let与const

        如果要说起es6,首先当然要说说let与const,那let又是什么,let,其实是es6新推出的,用来定义变量的关键字,用来取代已经老旧的var。

    let的特点:有块级作用域,意思就是,变量的有效范围,只在它所在位置的一前一后的两个大括号中间。

                      没有预处理,意思是,不能在声明变量之前使用它。

                      不能重复定义。

    let的作用与应用:作用就是定义一个变量,应用在循环遍历监听,比var方便很多

let btns = document.getElementsByTagName("button");
    for( i = 0;i

    const:定义一个常量,不可改变,其他的特点与let相同

2.解构赋值

        解构赋值的主要理解就是,从数组或者对象中取值,然后赋值给多个变量。

        而解构赋值的用途多用在给函数的多个形参赋值的时候。

        

 //首先声明一个对象,一个数组
  let obj = {
      name:"小明",
      age:10
  }
  let arr = [1,2,"333"];

  //用解构赋值的方法,将obj中的name,age属性赋值给全局变量name,age
  //注:如果要提取对象中的属性,声明变量时,一定要用大括号,大括号中的变量名,会一一对应
     //目标对象中的同名属性
  let {name,age} = obj;
  //用解构赋值的方法,将arr中下标为0,1的数据赋值给了全局变量a,b
  //注:如果要提取数组中的数据,则声明变量时,要用中括号括住,每个变量会与数组中相应的下标
     //一一对应
  let [a,b] = arr;

  console.log(name,age);//小明 10
  console.info(a,b);    //1 2

  //使用解构赋值的方法传递参数
  function fun({name}) {
      console.log(name);
  }
  fun(obj)

3.模板字符串

        在使用字符串加变量拼接成一个新的字符串的时候,我们都需要用引号,加号,引号,加号之类的方法去拼接,这样的效率无疑是非常低下的,而es6给我们提供了模板字符串,让字符串加变量变得简便了很多。

        es6模板字符串的拼接方式为 `` 两个重音符,把要拼接的字符串与变量写在里面,而变量则要写在 ${} 里面

         `这里写字符串${这里是变量}字符串 `

let usernmae = "kobi",age = 40;
  
  //相对于旧的拼接方式,新的模板字符串无疑是非常方便的
  let str = `我叫${usernmae}我今年${age}岁了`;
  let str2 = "我叫"+usernmae+"我今年"+age+"岁了";
  
  console.log(str);//我叫kobi我今年40岁了

4.对象的简写方式

        在es6中,对象中的属性和方法都是可以简写的

            属性:如果在全局作用域中有同名属性,则属性值,可以省略不写,只写属性名就行

            方法:方法可以省略function

            

let username = "2333";

  let obj = {
    username,
    shuo(){
        console.log("我也不知道我要说什么");
    }
  }
  console.log(obj);
  obj.shuo();//我也不知道我要说什么

5.箭头函数

    在es6中,新增了一种声明函数的方式,即为箭头函数

    let 函数名 = (参数) =>{函数体}

    箭头函数与普通函数最大的区别就是    this,箭头函数没有自己的this,箭头函数的this,在于定义箭头函数时,它的外部,是否有普通函数,如果有,则普通函数的this就是箭头函数的this,如果没有,则this为window。

    

 var obj = {
        name:"obj",
        fun8:()=>{
            console.log(obj.name);
        }
    };

    //外部有常规函数,this为常规函数的this,即为obj;
    function fun5() {
        console.log(this)
        let fun6 = () => {
            console.log(this)
        }
        return fun6;

    }

    //外部没有常规函数,this为window
    let fun7 = () => {
        console.log(this)
    }

    fun5.call(obj)();// obj
                     // obj
    fun7();          //window

    接下来是箭头函数的一些书写规则

let fun1 = name => console.log(name) // 一个形参时,形参位置可以没有括号
    let fun2 = (name,age) => console.log(name,age)//两个即两个以上的形参,则需要括号,形参之间用逗号隔开;
    let fun3 = name => name//如果函数体只有一行且没有大括号,那么这一行的执行结果会被直接返回
    console.log(fun3("小明"));// 小明
    let fun4 = (naem,age) => {
        console.log(name);
        console.log(age);
    }//如果有两条以上的函数体,则需要大括号

6.三点运算符

        三点运算符是es6为了取代arguments而定义的,因为arguments只是一个伪数组,没有一般数组的方法,而三点运算符是真的数组,而且比较灵活,不过三点运算符只能用来提取形参最后的参数。

        function fun(...value){}

function fun(...value) {
      console.log(value);
      
      //三点运算符拥有数组的一般方法
      value.forEach(function (item,index) {
          console.log(item,index);
      })

  }
  function fun2(a,...value) {
      console.log(value);
  }
  fun(1,2,3,4); // [1,2,3,4]
  fun2(1,2,3,4);// [2,3,4]

        let arr = [1,6];

        let arr2 = [2,3];

        let arr3 = [1,...arr2,6] // arr3 = [1,2,3,6]

        这样可以方便快捷的使数组进行拼接

7.形参默认值

        形参默认值还是比较简单的,就是在定义形参的时候,给它赋一个默认值就好了

let fun = (name = "wu",age = 0) =>{
      console.log(name,age);
  }

  fun();//wu 0
  fun("小明",18);//小明 18

    如果用户没有传入参数,则使用形参的默认值,如果用户传入了参数,则使用用户传入的参数。

8.promise函数

    promise函数是es6为了解决回调函数层层嵌套,也就是回调地狱从而创建的。

    promise函数是用来表示未来要发生的某一件事(通常是异步操作),promise是一个构造函数,用来创建promise对象

 
  
let fun = () => {
      let promise = new Promise(function (resolve,reject) {
          console.log(1);
          setTimeout(function () {
              //用来模拟ajax调用的成功与失败
              let num = Math.random();
              if(num>0.5){
                  //将状态变为成功
                  resolve("成功了");

              }else {
                  //将状态变为失败
                  reject("失败了");
              }
              console.log(num);
          },2000)
      })
      return promise;
  }



  fun()
      .then(
          //成功的回调函数,如果状态变为fullfilled则会自动执行
          function (data) {
            console.log(data,"一次调用成功");
           
          },
          //失败的回调函数,如果状态变为rejected则会自动执行
          function (data) {
            console.log(data,"一次调用失败");
          }
      )
      


    promise有三个状态,pending初始化状态,fullfilled:成功状态 ,rejected:失败状态

                  刚开始时,promise的状态为pending初始化,在某个时刻,如果调用resolve()函数则状态变为fullfilled成功

                                                                                                             如果调用reject()函数,则状态变为rejected失败

                   当成功或者失败状态触发时,则promise对象的then方法则会调用相应的(成功或者失败)的函数。

     promise还可以进行链式调用

fun()
      .then(
          //成功的回调函数,如果状态变为fullfilled则会自动执行
          function (data) {
            console.log(data,"一次调用成功");
            //如果成功,则继续调用该方法,并把promise对象返回,进行链式调用
            return fun();
          },
          //失败的回调函数,如果状态变为rejected则会自动执行
          function (data) {
            console.log(data,"一次调用失败");
          }
      )
      .then(
          function (data) {
              console.log(data,"二次调用成功");
          },function (data) {
              console.log(data,"二次调用失败");
          }
      )

   9.Symbol属性   

        symbol属性是es6新增的一种属性

        symbol属性的特点是:symbol属性对应的值是唯一的,解决了命名冲突的问题

                                            symbol属性不可以与任何属性进行计算,哪怕是字符串的拼接

                                            for in for of 遍历时不会遍历到symbol属性

        如果要使用symbol属性的话,需要调用Symbol函数,返回值为symbol属性

                                             如:let symbol = Symbol();  let obj = {}; obj[symbol] = "hello";

        

//Symbol函数的返回值就是symbol对象
  let symbol = Symbol();
  let obj = {}
  obj.symbol = "11";

  console.log(obj);//symbol:"11"

  //Symbol函数还可以传入参数

  let symbol = Symbol('one');
  let symbol2 = Symbol('two');
  let symbol3 = Symbol();
  let symbol4 = Symbol();
  //任意两个symbol都不相等
  console.log(symbol3 == symbol4); // false
  console.log(symbol);// Symbol('one')
  console.log(symbol2);// Symbol('two')

        Symbol对象除了可以自定义之外,es6还提供了11个内置的symbol对象,用来指向相对应的方法。

        如:Symbol.iterator属性,指向的是该对象的默认遍历器方法。

        

10.iterator接口

        iterator接口是为了让所有数据类型拥有统一的访问机制。

        作用:为所有数据提供统一的,简便的访问接口。

                  能够让数据结构的成员按照某种次序排列。

                  es6新推出了一种遍历方式 for of ,而iterator则是为for of服务。

        iterator的原理:首先当数据进行遍历是,让指针对象(遍历器对象)指向数据结构的起始位置,当调用next方法时,指针对象后移一位,并且返回一个对象,包含两个属性,value 与 done,value表示的是指针对象所在位置属性的值,而done则表示数据结构是否已经结束(指针对象大于等于length)。原生具备iterator接口的数据类型才可以使用for of遍历。

 
let iterator =(arr) =>{
        //首先将指针对象指向数据类型的起始位置
        let nextIndex = 0;

        //然后返回的对象中有一个next方法
        return {

            //用于返回value属性,done属性
            next:()=>{
                return nextIndex < arr.length?{value:arr[nextIndex++],done:false}:
                    {value:undefined,done:true};
            }
        }
    }
    let arr =[1,2,"abc"];

    let bianli = iterator(arr);

    console.log(bianli.next());
    console.log(bianli.next());
    console.log(bianli.next());
    console.log(bianli.next());

11.Generator函数

        Generaator函数也是es6为了解决回调函数问题而设计的,Generator函数又称为可暂停函数。

        Generator函数第一次调用时不会执行,只有调用next方法时才会开始执行,Generator函数内部有 yield 语句,每当执行到yield时,则会暂停,如果用Generator函数返回的对象调用next方法,则会返回yield后面一行语句的执行结果,并且再次暂停,直到下次调用next方法。

        next方法的返回值是一个对象,value    done,value属性值是next函数的返回值,done则表示函数是否执行到最后。

        如果要使用Generator函数,则需要在正常函数的function后加一个*号。

function* getNews() {
        console.log(1)
        //变量a是下一个next方法传入的参数
        let a = yield 233
        console.log(a)

    }
    //开始不会执行
    var news = getNews();
    //只有在调用next方法时,才会执行,遇到yield则暂停,返回值是yield后面一行语句的执行结果

    console.log(news.next());//1
                             // {value: 233, done: false}
    console.log(news.next("我是next方法传入的参数"));//我是next方法传入的参数
                                                   //{value: undefined, done: true}

        接下来将用Generator函数来向服务器发送请求,获取数据。分别要获得新闻数据和评论数据,只有在新闻获取成功之后才获取评论。

//服务器获取新闻的url是http://127.0.0.1:3000/news?id=3
    //这个方法是通过jquery的ajax方法从服务器获取数据的。
    //传入url,获取到数据
    function getNews(url) {
        $.get(url,function (data) {
            console.log(data);
            let url = "http://127.0.0.1:3000"+data.commentsUrl;
            //   2.    如果新闻获取成功的话,再用拼接好的url获取评论
                        //传入的参数会成为一个yield语句的返回值,给获取评论的函数一个url
            send.next(url);
        })
    }

    //这是Generator函数,用来进行每一步的ajax请求
    function* sendXml() {
        //   1.   首先传入第一个url,获取新闻
        let url = "http://127.0.0.1:3000/news?id=3";
        url = yield getNews(url);
        //    3. 通过上一个函数得到url,获取评论
        yield getNews(url);
    }

    let send = sendXml();
    //    0   Generator函数开始执行。
    send.next();

    12.async函数

        async函数是es2017提出来,彻底解决异步函数调用的。

        async函数不需要像Generator函数一样调用next方法指向下一步,而是等待异步操作执行完之后自动调用下一步,返回的对象是promise对象,可以用then方法进行下一步的操作。

        async取代了*,await取代了yield。

        await的返回值,如果后面语句是表达式,则直接返回

                                  如果是函数的话,返回值就是一般函数的返回值

                                  如果是promise对象的话,返回值是resolve函数传入的参数。

        async的语法

async function foo() {
        //遇到await则等待后面的异步函数执行完毕才会执行下一步。
        let a = await 1;
        console.log(a);
    }

    foo()//1

        接下来将用async函数向服务器请求数据。

//这是想服务器请求数据的方法
  async function getNews(url) {

      //这个函数返回的是promise对象,
      return new Promise((resolve,reject) => {
          console.log(1);
          $.ajax({
              method:"GET",
              url,
              //如果请求成功,则await的返回值为resolve的参数
              success:(data)=> resolve(data),
              error:(error) => resolve(false)
          })
      })
  }

  async function send() {

      //进行新闻的请求
      let url = "http://127.0.0.1:30001/news?id=1"
      let result = await getNews(url);

      //如果请求失败,则给用户提示,并且结束函数
      if(!result){
          alert("暂时没有新闻内容,请稍后再来");
          return;
      }
      console.log(result);

      //如果成功,则继续请求评论
      result = await getNews("http://127.0.0.1:3000"+result.commentsUrl);
      console.log(result);
  }

  send();

13 javascript中的class

        终于,在es6中,js也有类的概念了,所谓类,其实是一个抽象的概念,比如,我定义人这个类,人可以走,可以吃饭,我就在类中,写好吃饭,走,两个方法,但是因为每个人的名字,性格等待都不相同,我就在构造方法中,写入两个形参,名字,性格,然后让this.name = name ,这样就可以让每个人类的实例,可以有不同的姓名,性格等,而且他们还拥有人类的方法。

        通过class关键字创建一个类 class people{}

        在类中,可以通过constructor关键字来定义构造方法。

        如果要在类中定义方法的话,不能有function关键字,而是直接书写方法 如:getName(){};

        类与类之间通过extends来进行继承。并且需要在子类的构造方法中调用super()方法调用父类构造函数。

        通过new关键字,new类名来创建一个实例。

        

//这是定义的人类
  class people{
      //构造方法,人有名字,有年龄,所以传入相应的参数
      constructor(name,age){
          this.name = name;
          this.age = age;
      }
      //这是父类的获取名字的方法,实例可以直接打点调用该方法
      getName(){
          console.log(this.name);
          console.log("这是父类的方法");
      }
  }

  //这是我,继承的人这个类
  class wo extends people{
      //子类构造方法
      constructor(name,age,gongzi){
          //必须调用父类构造方法,并且super关键字需要是第一行
          super(name,age);
          this.gongzi = gongzi;
      }
      
      //因为父类无法满足,所以在子类重写了该方法
      getName(){
          console.log(this.name+" "+this.gongzi);
          console.log("这是子类的方法");

      }
  }

  let ren = new people("呵呵",1);
  ren.getName();
  //呵呵
  //这是父类的方法

  let me = new wo("哈哈",2,100000000);
  me.getName();
  //哈哈 100000000
  //这是子类的方法

14,ES6数组,对象,字符串,Numbler 扩展方法

        接下来说说es6对于数组,对象,字符串,Number 扩展的一些方法,先从字符串说起。

            字符串扩展方法:    includes(str) // 判断字符串是否包含制定的字符串。

                                           startWith(str)//判断是否以指定字符串为开头。

                                            endsWith(str)//判断是否以字符串为结尾

                                            repeat(count)//重复指定次数

let str = "abcdefg";

  console.log(str.includes("c"));//true;
  console.log(str.startsWith("a"));//true
  console.log(str.endsWith("g"));//true
  console.log(str.repeat(2));//abcdefgabcdefg

                Number的扩展方法:         Number.isFinite(i)//判断是否是有限大的数

                                                        Number.isNaN(i)//判断是否是NaN

                                                        Nubber.isInteger(i)//判断是否是整数

                                                        Number.parseInt(i)//将字符串转换为数字

                                                        Number.trunc(i)//去除小数点 

             二进制与八进制数值表示法: 二进制用0b, 八进制用0o


    console.log(0b1001);//9
    console.log(0o56);//46
    console.log(Number.isFinite(Infinity));//false
    console.log(Number.isNaN(NaN));//true
    console.log(Number.isInteger(123.3));//false
    console.log(Number.parseInt("123acc"));//123
    console.log(Math.trunc(123.33));//123

                    数组的方法:        Array.from() // 用来将一个伪数组(arguments之类的)转换成真数组。

                                              Array.of() //用来将传入的参数转换成数组

                                              Array.Prototype.find(function(iteam,index){})//返回数组中以第一个条件为true的数据

                                           Array.Prototype.findIndex(function(iteam,index){})//返回数组中以第一个条件为true的数据下标

function test(){
      let arr = Array.from(arguments)
      arr.forEach(function (iteam,index) {
          console.log(iteam);
      })
  }

  test(1,1,2,3,3,3);//

  let arr = Array.of(1,2,3,4,"abc");

  arr.forEach(function (iteam,index) {
      console.log(iteam,"我是Array.of()转化成数组的数据");
  })

  //find方法与filter方法比较类似,不过find方法只会返回第一个
  let arr2 = arr.find(function (iteam,index) {
      return iteam>2
  })
  console.log(arr2,"我是find方法");

  let arr3 = arr.findIndex(function (iteam,index) {
      return iteam > 2
  })
  console.log(arr3,"我是findIndex方法");

                对象的扩展方法        Object.is(v1,v2)//判断两个数据是否完全相等

                                                Object.assign(target,source1,source2);//将一个或多个对象的数据复制到目标对象上

                                                 可以直接操作__proto__属性

    

console.log(0 == -0);//true
    console.log(NaN == NaN);//false
    console.log(Object.is(0, -0));//false
    console.log(Object.is(NaN, NaN));//true

    let obj1 = {};
    let obj2 = {name:"小明"};

    Object.assign(obj1,obj2);
    console.log(obj1);//{name:"小明"}


    let obj3 = {qian:5000000000};
    let obj4 = {};

    obj4.__proto__ = obj3;
    console.log(obj4.qian);//5000000000

15.深度克隆

          什么是深度克隆呢

                    浅克隆:修改克隆的对象,原对象也随之改变,即位浅克隆,有时浅克隆是有风险的。

                    深度克隆:如果修改了克隆之后的对象,对原对象没有影响的话,就是深度克隆。

         如果复制一个基本数据类型,再新的变量修改的话,不会对原数据有影响,但如果复制的是一个引用类型的话,如果修改新的引用,也会对原对象有所影响。

        下面是几个拷贝数据的方法 :        Object.assign(target,ziyuan)//将资源对象,复制到目标对象   浅拷贝

                                                             Array.prototype.concat(arr)//用于连接两个或者多个数组,返回值是连接后的数组 

                                                                                                                                                            浅拷贝

                                                             Array.prototype.slice(num,num)//用于分割数组                     浅拷贝

                                         JSON.parse(JSON.stringify())//将一个对象转化成json字符串,然后在转换回来                                                                                                                                                              深拷贝                                      

        下面将自定义一个方法,进行对象的克隆,使修改新的对象时,不会对原对象有影响。

        主要就是将对象中的基本数据类型复制到新对象中,如果其中还有对象的话,就遍历对象,接着复制基本数据类型。           

  

//我们定义checkType这个方法,是因为我们要对不同的数据类型进行不同的操作。
      //如:遇到基本数据类型,直接复制就可以,而遇到数组或者对象,就要遍历他们中的每一项值,在进行值的复制

  //因为typeof返回的数据类型只有六种(String Number boolean Undefined object function)
  //所以我们自己定义一个方法,可实现返回所有的数据类型
  let checkType = (target) =>{
      //通过Object的toString方法,并且用call调用传入要识别的对象,然后返回对应类型的字符串
      return Object.prototype.toString.call(target).slice(8,-1);
  }


  //这是克隆方法,只要传入目标对象,就可以返回克隆好的对象,并且修改克隆对象,对新的对象也不会有影响
  function clone(target) {
      //首先创建一个空对象来接收要复制的对象
      let newTarget = null;

      //如果要遍历的对象是一个数组,那么newTarget就是一个数组
      if(checkType(target) == "Array"){
          newTarget = [];
      }else if(checkType(target) == "Object"){
          newTarget = {};
      }else{
          //如果既不是数组,也不是对象,直接返回就可以了,因为基本数据类型,没有浅克隆这个概念
          return target;
      }
      
      //用for in方法遍历数组中的每一项值,如果是基本数据类型,就直接用newTarget的对象接收。
      //如果是对象或者数组,就接着遍历其中的每项值,然后返回一个新的对象或者数组,用newTarget接受
      for(let i in target){
          if(checkType(target[i]) === "Array" || checkType(target[i]) === "Object"){
              //用递归的方法去遍历对象(数组)中的数组或者对象。
              newTarget[i] = clone(target[i]);
              console.log("遍历到一个对象或数组");
          }else {
              newTarget[i] = target[i];
              console.log("遍历到一个基本数据类型");

          }
      }
      //最后,返回一个新的对象
      return newTarget;
  }
  let obj = {
      name:1,
      info:{
          age:2
      },
      class:"yiban"
  }
  console.log(clone(obj));

16.set与map容器

        js中的容器与数组比较类似,set容器:无序的,不可重复的多个value的集合体。         说白了,就是不能重复的数组

                                                   map容器:无序的key value组合,key值不能重复

        set容器的语法:let setarr = new Set([1,1,2,3,4]); 

                                new Set()即可,形参传入数组,数组中传入想穿的数据。

        map容器语法:let maparr = new Map([["name","xiaoming"],["age",18]])  

                               //new Map()即可,形参传入二维数组,一维数组是大的容器,二维数组中第一个值是key,第二个是value

        



17.for of 与set,为数组去重

        set与map容器,都可以用for of去遍历,接下来我将用for of与set为一个数组去重

        

let arr = [1,1,2,5,4,6,9,8];
  let arr1 = []
  //因为Set容器不许有重复的数据,所以会自动去掉重复数
  let setarr = new Set(arr);
  
  //然后用for of遍历setarr,将数据放入新数组。
  for(let i of setarr){
      arr1.push(i)
  }
  console.log(arr1);



最后还有es7的两个东西,幂和数组的includes

        幂 **  

        a ** b 就是a的b次方幂

        Array.prototype.includes(value)表示数组中是否有这个数据


console.log(5 ** 5);3125
  let arr2 = [1,2,3,"abc"]
  console.log(arr2.includes(1));//true
  console.log(arr2.includes("a"));//false

        


你可能感兴趣的:(ES6学习的个人总结)