5

es5、es6

1.super
  1. super关键字使得子类调用了父类中的构造函数,父类可以使用子类传进来的属性进行各种运算,
  2. super 关键字 还可以调用父类的方法
  class Father{
    constructor(x,y){
         this.x=x;
         this.y=y;
     }
     
    sum(){
         console.log(this.x+this.y)  
       }
  
    say(){
         return "我是爸爸" 
      }
  }
 
  class Son extends Father{
    constructor(x,y){
       //调用了父类中的构造函数   
        super(x,y)
       //子类独有的属性
        this.x=x;
        this.y=y
      }
      
    say(){
       console.log(super.say())
    }
    
    //子类独有方法
    subtract(){
     console.log(this.x-this.y)
    }
  }
  
  let son=new Son(5,3);
  son.subtract();
  son.sum();
tips: 继承中的属性或者方法查找原则:就近原则
  • 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
  • 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
  • 子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,再使用子类构造方法)
  • es6 中类没有变量提升,必须先定义类,才能通过类实例化对象\
  • 类里面的共有的属性和方法一定要加this使用
2.this指向
  • constructor (构造函数)里面的this 指向的是 创建的实例对象
  • 方法 谁调用了方法,那么它的this就是指向它
 var that //等于构造函数里this 即ldh这个对象
  class Star{
    constructor(name,age){
        that=this
        this.name=name
        this.age=age
        this.btn=document.querySelector('button');
        this.btn.onclick=this.sing
    }
  }
  
  sing(){
    /* 这个sing方法里的this,指向的是btn  这个按钮,因为这个按钮调用了这个函数 */
     console.log(this)
     console.log(this.name) //输出undenfind
     console.log(that.name) //输出ldh
   }
   
   dance(){ 
    /* 这个dance里面的this 指向的是实例对象 ldh 因为是ldh调用了这个函数 */
    console.log(this)
   }
   
   let ldh=  new Star(ldh,18)
   ldh.dance()
3.构造方法和原型(模拟面向对象)
  • es5不使用prototype原型对象
   function Star(name,age){
      this.name=name;
      this.age=age;
      this.sing=funtion(){
         console.log(我会唱歌) 
      }
   }
   var ldh=new Star('刘德华',18);
   var zxy=new Star('张学友',19);
   /* new多个,基本属性不会,但sing方法会开辟多个不同的内存空间,存在内存浪费的现象 */。
  • es5使用构造函数prototype原型对象
   function Star(name,age){
      this.name=name;
      this.age=age;
      Star.prototype.sing=funtion(){
         console.log(我会唱歌) 
      }
   }
   
   Star.prototype ={
    /*如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数*/ 
    constructor:Star
   }
   
   var ldh=new Star('刘德华',18);
   var zxy=new Star('张学友',19);
   ldh.sing()
   /* new多个,基本属性不会,但sing方法会开辟多个不同的内存空间,存在内存浪费的现象 */。
  • 原型对象

    • 原型是一个对象,我们也称为prototype为原型对象
    • 构造函数通过原型分配的函数是所有对象所共享的。
    • js规定, 每一个构造函数都有一个prototype属性,指向另一个对象,注意这个prototype就是一个对象,这个对象的所有属性方法,都会被构造函数所拥有。
    • 我们可以把这些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
    • 一般情况下,我们的公共属性定义的构造函数里面,公共的方法我们就放到原型对象上
    • 对象身上(ldh对象)系统自己添加一个__proto__指向我们构造函数中的原型对象
    • ldh.__proto__和构造函数Star.prototype 是等价的
  • __proto__和 prototype 的区别

    • __proto__new出来的实例的的原型对象
    • prototype 是构造函数的原型对象

      tips: es5的构造函数方法很好用,但是存在浪费内存的问题,可以通过构造函数的原型对象来存放方法,使得方法在不同对象中共享,起到节约内存的作用。
4.原型链
  • 实例对象 proto (找不到的再向上找)-> 构造函数的原型对象 __proto__(找不到再向上找)->Object.prototype__proto__(找不到再向上找)-> null
  • js成员的查找机制

    • 当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性 。
    • 如果没有就查找它的原型(也就是__proto__指向的prototype原型对象)。
    • 如果还没有就查找原型对象的原型(object的原型对象)。
    • 依次类推一直找到Object为止(null)。
        function Star(name,age){
           this.name=name;
           this.age=age;
         }

        Star.prototype.sing=function(){
          console.log("我会唱歌");     
        }

        Star.prototype.sex='女' //构造函数原型成员 ,优先级中等
        Object.prototype.sex="男"//object对象的原型成员 ,优先级最低
        var ldh =new Star('刘德华',18)
        ldh.sex="男" //实例对象的原型成员 优先级最高
        console.log(ldh.sex)

        //打印这个实例向上找,可以找到Object
tips: 每个对象里都有 __proto__这个属性
5.利用原型对象,扩展内置对象方法
console.log(Array.prototype) 可以打印js的一些关于数组的api

 //在Array对象上添加自定义方法
Array.prototype.sum=function(){
   var sum=0;
   for(var i=0;i<thsi.length;i++){
       sum+=this[i];
   }
   return sum;
 }
 
var arr=[1,2,3]; 
console.log(arr.sum())
var arr =new Array(11,22,33)
arr.sum();

//不可采用以下方法加入方法
 Array.prototype=
 {
  sum: function(){
       var sum=0;
       for(var i=0;i<thsi.length;i++){
       sum+=this[i];
    }
      return sum;
   }
 }
tips: 自己加的原型方法会高亮,不可采用对象的方式去添加原型方法,会覆盖原先就存在的方法。
6.call 方法
  • call可以调用函数。
  • 可以改变这个函数的this指向。
  • 第一个参数是this的指向要被改变到这个参数的。
  • 第二个开始 就当做是普通函数的普通参数就可以了,只是this指向改变了,但方法里一些操作没有改变
  • es5用call绑定this继承了属性
   function fn(x,y){
     console.log('我想喝手磨咖啡');
     console.log(this);
     console.log(x,y);
   }
   
   var o={
      name:'andy'
   }
  
  fn.call() 
  
  /* 此时这个函数的this,就指向了o这个对象,指向哪个对象根据第一个参数决定*/
  fn.call(o,1,2)  
  1. 父构造函数
  function Father(name,age){
    //this 指向父构造函数的对象实例
     this.name=name;
     this.age=age;
  }
  
  2. 子构造函数
  //这个score用的son自己的属性
   function Son(name,age,score){
      //this 指向子构造函数的对象实例,
      //用call来调用Father这个构造函数,并把指向改成子类的构造函数的this,就实现了继承
      Father.call(this,name,age)
      this.score=score
    }
   var son=new Son('刘德华',18,200)
   console.log(son)
7. prototype 继承方法

原型对象(prototype)继承方法,通过原型链向上找规则,
Father实例(找不到向上找)->Father的原型对象的方法
就可以继承方法了,且子son方法定义自己的方法时不会影响到父

 //Father 是es5的构造函数
 son.prototype=new Father()
 son.prototype.constructor=son
 
8. 类的本质

类的本质其实还是一个函数 我们也可以简单的认为类就是构造函数的另外一种写法

  • es5 通过构造函数+原型实现面向对象 编程有以下特点

    • 构造函数有原型对象prototype
    • 构造函数原型对象prototype里面有constructor指向构造函数本身
    • 构造函数可以通过原型对象添加方法
    • 构造函数创建的实例对象有__proto__原型指向 构造的原型对象
  • es6

    • class有原型对象prototype
    • class的prototype里面有constructor指向构造函数本身
    • class可以通过原型对象添加方法
    • class创建的实例对象有__proto__原型指向 构造的原型对象
9. 数组方法
  • forEach 迭代遍历数组,break和retrun不会终止

    var arr= [1,2,3];
    arr.forEach((value,index,array)=>{
        console.log("每个数组元素"+value)
        console.log("每个数组元素的索引号"+index)
        console.log("数组本身"+array)
    })
    • filter 主要用于筛选数组

           var
           arr=[12.66,4,88]
           var newArr=arr.filter((value,index,array)=>{
             return value>=2  //满足条件就把值放到新数组里
           })
      tips:返回的是一个新数组,不会影响原来的数组
  • some

    主要用于检测数组中的元素是否满足指定条件,通俗点查找数组中是否有满足条件的元素

   var
   arr=[12.66,4,88]
   var flag=arr.some((value,index,array)=>{
     return value>=2  //满足条件就是true
   })
   
   arr=[12.66,4,88]
   var flag=arr.some((value,index,array)=>{
    if(value>30){
        return true  
    }
   })
   
tips:返回的是一个布尔值,如果查找到这个元素就返回true,不再进行循环,效率更高。
10. 字符串方法

trim 去除左右两边的空格,但不会去除中间的空格

str.trim()
11. object.defineProperty()

定义对象中新属性或修改原有的属性

object.defineProperty(obj,prop,descriptor)

object.defineProperty的参数

参数 是否必需 类型 说明
obj true Object 目标对象
prop true String 需新定义或修改的属性的名字
descriptor true Object 目标属性所拥有的的特性
 var obj={
     id:1,
     pname:"小米",
     price:1999
 }
 
 //对对象定义新属性并赋值,以前的写法
 obj.num=1000;
 obj.price=99;
 //现在的写法
 
 Object.defineProperty(obj,'num',{      
 })

第三个参数descriptor的参数

参数 是否必需 类型 说明
value false mixed 设置属性的值 默认undefined
writable false boolean 是否可以重写 默认false
ebumerable false boolean 目标是否可以被枚举(遍历),默认false
configurable false boolean 目标属性是否可以被删除或是否可以再次修改特性true/false 默认为false
tips: 注意新定义的descriptor 都是默认为false 用obj={} 来定义的因为没有定义是否可以被XX操作所以都是true
12.函数

所有的函数都是Function的实例(对象),函数也是个对象,万物皆对象

一、 函数的定义方式
1.自定义函数(命名函数)

function fn(){};

2.函数表达式(匿名函数)

var fun =function(){
    
}

3.利用new Function (不推荐,效率低)

new Function('参数1','参数2','函数体')
参数 是否必需 类型 说明
参数1 false String 第一个参数
参数2 false String 第二个参数
函数体 false String 第三个参数
tips:如果只有一个参数那么就是函数体

二 、 函数的调用方式
1.普通函数

this 指向window

function fn(){
   console.log('人生的巅峰') 
}

fn() (window.fn())
fn.call()

2.对象的方法

this指向o

 var o ={
   sayHi:function(){
         console.log('人生的巅峰')  
   }  
 }
 
 o.sayHi();

3.构造函数

this 指向实例对象

function Star(){};

new Star();

4.绑定事件函数

this 指向是函数的调用者btn这个按钮对象

//点击了按钮就可以调用这个函数
btn.onclick=function(){};

5.定时器函数

this指向的是window

这个函数式定时器自动1秒钟调用一次

setInterval(function(){     
},1000);

6.立即执行函数

this 指向window

(function(){
  console.log('人生的巅峰') 
})()
tips: 立即执行函数是自动调用
调用方式 this指向
普通函数调用 window
构造函数调用 实例对象,原型对象里面的方法也指向实例对象
对象方法调用 该方法所属对象
事件绑定方法 事件绑定对
定时器函数 window
立即执行函数 window
13.改变this指向
  • call

    1. 调用函数
    2. 可以改变函数内部的this指向
     var o={
        name:"1"
     }
     functon fn(a,b){
         console.log(a+b)
     } 
     fn.call(o,1,2) 
tips: 后两个参数是形参 用于参与fn的一些对象,主要用于在es5中实现继承
  • apply

    1. 调用函数
    2. 可以改变函数内部的this指向
    3. 主要应用 apply 借助于数学内置对象求最大值和最小值。
       var o={
        name:"1"
     }

     functon fn(a,b){
         console.log(a+b)
     }

    fn.apply(o,[1,2]) 
    var arr=[1,66,4]
    //如果不想改变this(指定对象)就写个null,但不合适写Math就行了
    Math.max.apply(Math,arr)
tips:参数必须是数组,但打印后却是字符串或是数字(根据数组里的数据类型,判定)
  • bind

    1. 不会调用函数
    2. 可以改变函数内部的this指向
    3. 返回的是原函数改变this之后产生的新函数(深拷贝)
    var o={
       name:"1"
     }
     functon fn(a,b){
         console.log(a+b)
     }
     var f= fn.bind(o);
     f();
     //亦或者是
      functon fn(a,b){
         console.log(a+b)
      }.bind(this)
14. call、apply、bind总结
  • 相同点:都可以改变函数内部的this指向
  • 区别点:

    • call和apply会调用函数,并且改变函数内部this指向。
    • call和apply传递的参数不一样,call传递参数aru1,aru2形式,apply必须数组形式[arg]
    • bind 不会调用函数,可以改变函数内部的this指向
  • 主要应用场景:

    • call经常做继承。
    • apply经常跟数组有关系,比如借助于数学对象实现数组最大值和最小值
    • bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向,ajax的this指向
15. 严格模式
  • 作用:

    • 消除了js语法的一些不合理、不严谨、减少了一些怪异行为。
    • 消除代码运行的一些不安全之处,保证代码运行的安全。
    • 提交编译器效率,增加运行速度。
    • 禁用了es的未来版本中可能会定义的一些语法,为未来新版本的js做好铺垫。比如一些保留字如:class,enum,export,extends,import,super不能做变量名
  • 变化

    • 我们的变量必须先声明再使用
    • 我们不能随意删除已经声明好的变量
    • 在严格模式中全局作用域中函数中的thisundefined而不是window
    • 以前构造函数不加new也可以调用,当前普通函数,this指向全局,在严格模式下不能使用了,this指向undefined
    • new 实例化的构造函数指向创建的对象实例
    • 定时器的this 还是指向window
    • 函数不能有重名的参数
    • 函数必须声明在顶层,不允许在非函数的代码块内声明函数。比如if和for的花括号里定义函数,但函数嵌套函数是可以的。
    //为整个脚本开启严格模式

         <script>
         'use strict';
          </script>

          <script> 
          (function()){
            'use strict';
          }() 
          </script> 

          //为某个函数开启严格模式

          <script> 
             function fn(){
                'use strict';
                 /*里面的代码按照严格模式执行*/
              }

              function fun(){
                 /*里面的还是按照普通模式执行*/
               }

          </script>
tips:兼容ie10以上,ie10以下会忽略这个模式
16. 高阶函数

高阶函数- 函数可以作为参数传递,参数的接收方就是高阶函数,即 fn

 function fn (a,b,callback){
     console.log(a+b);
     callback && callback()
  }

 fn(1,2,function(){
    console.log(我是最后调用的);
 })
 
17. 闭包
  • 闭包指有权访问另一个函数作用域中变量的函数,简单理解就是,一个作用域可以访问另外一个函数内部的局部变量,(closure 是闭包)此时就有闭包的产生,闭包也是高阶函数
  • 这里fn是闭包,fun调用了fn的变量,也就是被调用变量所在的函数,就是闭包函数
 function fn (){
     var num=10;
     function fun(){
      console.log(num)
     }
     fun ()
 }

fn
  • 我们fn外面的作用域可以访问fn 内部的局部函数

function fn(){
    var num=10;
    return function(){
     console.log(num)   
    }
}

//这里f保存的是个函数
var f=fn()
//这里输出的是num
f()
for (var i=0;i<lis.length;i++){
/*利用for循环创建了4个立即函数*/
/*立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数,都可以使用它的i这个变量*/


/*这里的i是从底下的那个i传进来的*/
(function(i){

lis[i].onclick=function()  {
    console.log(i)
 }
})(i) 
tips:闭包的主要作用:延伸变量的作用范围。但闭包容易照成内存泄漏,它一直不释放资源,闭包总结:闭包是一个函数,闭包延伸了作用域范围
18. 递归
  • 函数内部自己调用自己,这个函数就是递归函数,递归函数必须加退出条件,利用递归函数求1-n的阶乘。
    function fn(n){
      if(n==1) return 1;
       return n*fn(n-1);
    }

    console.log(fn(3))
    执行过程

    return 3*fn(2)
    return 3*(2*fn(1))
    return 3*(2*1)
    return 6
  • 用递归求斐波那契数列(兔子序列)
    function fb(n){
      if(n===1 || n===2){
          return 1
      }
      return fn(n-1)+fb(n+2);
    }

    console.log(fb(3))
    console.log(fb(3))
  • 用递归来遍历数据
     var data=[
     {
       id :1,
       name:'家电'
       goods':[
        {
           id :11,
           name:'家电11'
        },
         {
           id :12,
           name:'家电12'
        }
       ]
     }
      {
       id :2,
       name:'家电2'
       goods':[
        {
           id :13,
           name:'家电13'
        }
       ]
     }
    ]

    function getID(json,id){
     var o ={};
     json.forEach(function(item)) {
      if(item.id==id){
         console.log(item);
         o=item;    
      }else if(item.goods&&item.goods.learth>0){
         o= getID(item.goods,id)
       }
      }
     } 
     console.log(getID(data,1))

tips: 开辟内存空间,容易照成死递归,出现栈溢出。在forEach里面执行递归,不加退出条件,循环已经帮你加了。

19. 浅拷贝和深拷贝
  • 浅拷贝只是拷贝一层,更深层次对象(对象或数据等复杂数据类型)级别的只拷贝引用。
    1.for 循环实现浅拷贝
    var obj={
     id:1,
     name:"andy", 
     msg:{  //这个对象是深层次对象会被浅拷贝,会被拷贝地址,修改o同时会修改obj,这个就是浅拷贝
         age:18
     }
    }
    
     var o={}
     for(var k in obj){
      //k 是属性名
      // obj[k] 属性名
       o[k]=obj[k];
     }
     console.log(o);
     o.msg.age=20;
     console.log(obj)

2.es6的语法糖实现浅拷贝

  Object.assign(o)
  /*主要用来对,对象赋值, key值相同的会覆盖
  其他没进行赋值的不会处理,因为是浅拷贝所以会影响原数组
  */
  • 深拷贝拷贝多层,每一级别的数据都会拷贝
    1.用递归的方式来实现深拷贝
    function deepCopy(newobj,oldobj){
     for(var k in oldobj){
      var item=oldobj[k];
      if(item instanceof Array){
        newobj[k]=[];
       //判断是否是数组
        deepCopy(newobj[k],item)
      }else if(item instanceof Object){
        //判断是否是对象
         newobj[k]={};
         deepCopy(newobj[k],item)
      }else{
       // 简单数据类型
        newobj[k]=item;
       }
      }
    }
2.用JSON.stringify()和 jSON.parse() 来实现 深拷贝
tips: 数组也属于Object 所以要把Array判断写在object的前面。

总结:浅拷贝,深层次的数据如数组和对象只会拷贝引用,修改拷贝后的数据会同时修改原来的被拷贝的的数据,深拷贝,是对数组和对象开辟不同的空间,被拷贝的的数据。

20. 正则表达式

   灵活性、逻辑性和功能性非常的强,
可以迅速地用极简单的方式达到字符串的复杂控制

  • 创建正则表达式
    1.利用RegExp 对象来创建 正则表达式
    var regexp=new RegExp(/123/)
    console.log(regexp) 

2.利用字面量,创建正则表达式,即用//即注释的中间写上规则匹配就是正则表达式了

     var rg=/123/;
     /*
      可用test 方法来检测是否符合正则表 返回true或false
     */
     var rg=/123/;
     console.log(rg.test(123));
  • 边界符 ^ $
    var rg=/^abc/ ^匹配的是开头,这里的是abc
    var rg=/^abc$/ 精确匹配 只有输入abc 才会匹配
  • 字符类 []
    表示有一系列字符可供选择,只要匹配其中一个就可以了。这个只能多选一要和量词符,匹配使用。量词是设定某个模式出现的次数。
      /* 只要包含a,或者b,或c,其中一个就可以了 */
     var rg=/[abc]/

    /* 只能选择一个a或者b或者c其中的一个 三选一 */
       var rg=/^[abc]$/

    /* 只能选择一个a-z,26字符中其中的一个字符,26选一
    表示到a到z的范围 可以在[]中添加各种字符组合
    */  
      var rg=/^[a-zA-z]$/

    /* 如果中括号里 ^ 表示取反的意思 不要和边界符 ^ 混淆 取反即      以下就不能是 a-z和A-z 
    */ 
      var rg=/^[^a-zA-z]$/
  • 量词符
      如果前面的那个没有加上中括号,那么就作用于量词符前面那个的字符。有中括号就按照中规则里匹配的规则去实现。
     //* 相当于>=0 可以出现0次或者很多次

    var rg=/^a*$/;
    console.log(rg.test('')) 
    console.log(rg.test('aaa'))

    //+ 相当于>=1 可以出现1次或者很多次,不能不出现,即0次
      var rg=/^a+$/;
     console.log(rg.test('')) 
    console.log(rg.test('aaa'))

    //? 相当于 1 || 0  可以出现1次或者0次 
     var rg=/^a?$/;
     console.log(rg.test('')) 
     console.log(rg.test('a')) 
     console.log(rg.test('aaa')) 

    //{3}就是重复出现3次

    var rg=/^a{3}$/;
    console.log(rg.test('')) 
    console.log(rg.test('aa')) 

    console.log(rg.test('aaa')) 

    //{3,}出现大于等于3

    console.log(rg.test('')) 

    console.log(rg.test('aaa'))

    //{3,16}出现大于等于3并且小于等于16

    var rg=/^a{3,16}$/;

    console.log(rg.test(''))

    console.log(rg.test('a'))
  • 量词符和模式匹配
    模式是 :[a-zA-z] 某个规则
    量词符:{6,16} 这个规则的里字符可出现的次数 即只能出现6-16个a-zA-z 里的字符 且全部合起来只能有6-16个。
    var rg=/^[a-zA-z]{6,16}$/
  • 优先级 用小括号来表示优先级
    //这里有小括号所以表示 abc 重复3次
    var rg=/^(abc){3}/
    //这里没有小括号 c 重复3次
    var rg=/^abc{3}/
  • 可以用菜鸟正则表达式的测试工具 菜鸟工具

      菜鸟工具

  • 预定义类 简写正则
预定类 说明
d 匹配0-9之间的任一数字,相当于[0-9]
D 匹配0-9以外的字符,相当于1
w 匹配任意的字母、数字、和下划线,相当于[A-Za-z0-9_]
W 匹配任意的字母、数字和下划线以外的字符,相当于2
s 匹配空格(包括换行符、制表符、空格符等),相当于[trnvf]
S 匹配非空格(相当于3
  • 正则里还可以用 | 表示或者的意思
//座机号码验证 010-12345678 0591-1234567

 //第一种
 var reg=/^\d{3}-\d{8}|\d{4}-\d{7}$/
 //第二种
 var reg=/^\d{3,4}-\d{7,8}$/
 
 //手机号码的正则表达式
 var rg=/^1[3|4|5|7|8]\d{9}$/;
//qq号的正则 10000开始
var rg=/^[1-9]\d{4,}$/ 
  • replace 替换
var str=str.replace(/andy/,bady)
参数 说明
第一个参数 被替换的字符串或者正则表达式
第二个参数 替换为的字符串

返回值 是一个替换完毕的新字符串

tips: 正则表达式里面不需要加引号, 不管是数字型还是字符串型,正则表达式的中间不要有空格即//里添加的内容不要用空格来间隔

以下都是es6、es7的知识点

1.let关键字
  • let关键字声明的变量具有块级作用域,用来替代var ,主要用来防止内层变量覆盖外层变量,防止循环变量变成全局变量。
     if(true){
         let a=1;
         var b=3
     }

     console.log(a) //访问不到 undefined
     console.log(b) //访问的到,输出3
  • let关键字声明变量,没有变量提升未定义不能访问
  • 具有暂时性死区特性
      var num =10
      if(true){
        console.log(num)  undefined
        let num=1
      }

     /* num输出在块级作用域里,使用的是块级的作用域定义的变量,而且是在未定义前输出所以是undefined */
  • let 解决循环的变量问题
      for (var i=0;i<10;i++){
           console.log(i)
           setTimeOut(function(){
              console.log(`i:${i}`)
        })
      }
      在var定义的变量下,定时器里输出的都是10 
      因为此时循环已经结束了,i是最后的一个值。

      用let 可以正常循环输出
2.const关键字
  • 声明的常量具有块级作用域
  • 必须要赋初始值
  • 常量赋值后,内存地址(值)不能修改,分两种情况

    • 对于复杂数据类型,里面的值可以更改,但数据值本身不能更改
    • 对于普通数据类型,值就是不能更改
      const a =1
       a=3 //报错,值不能更改
      const arr=[1,2]
      arr[0]=3  //可更改,只是更改结构内部的值   arr=[3,2]
      arr=[34,44] //不可更改整体都更改,是地址的更改,不允许
  • 不存在变量提升 (先声明再使用)
tips: 如果让对象里的属性不可进行修改可以使用es5的方法 Object.freeze(arr) 此时 arr内部的属性也不能更改
3.解构赋值
  • 数组解构允许我们按照一一对应关系从数组中提取值,然后将值赋值给变量
    let [a,b,c]=[1,2,3] || [];
    console.log(a,b,c,d,e)
    a 、b、c 输出 1,2,3 d,e是undefined
  • 对象解构赋值
    let person ={name:'zhangsan',age:20}
    let {name,age}=person || {}
    console.log(name) //zhangsan
    console.log(age) // 20
    let {name:myName,ages:myAge}=person
    console.log(myName,myAge) //也可以输出
  • 解构和扩展运算符一起的使用
    //第一种情况,把整个的对象赋值给另一个读写
    let user = { a: 1,b: 2,c: 3,d: 4,e: 5}
    let 
    {
      aa = { a: user.a, b: user.b }, 
      bb = { ...user } 
    } = {}

    /*
    第二种情况,可以把对象的值分配到不同的对象
    */
    let users = {}, userDetails = {};
    ({ a: users.a, b: users.b, ...userDetails } = user);
    console.log(users, userDetails)

    //users {a:1,b:2}  userDetails {c:3,d:4,e:5}
  • 对象解构可以嵌套获取值
     const Tom={

         name: 'Tom jones',
         age:25,
         family:{
             mother: 'Norah Jones',
             father: 'Richard Jones',
             brother: 'Howard Jones'
         }
     }

     //只有在变量是underfine时,才能使用默认值 null false 0 都是有值的
     const { father:f,mother:m,brother='sss' } = Tom.family || {} ;

    //以上的f、m 是别名 输出用别名
  • 用数组解构来交换值
  let a=10
  let b=20
  [a,b]=[b,a]

  console.log(a,b) //a输出 20 b输出10
tips: 第二种情况,一定要加上括号。
4.箭头函数
  • 箭头函数是用来简化函数定义语法的
    function sum(num1,num2){
        return num1+num2
    }

    const sum=(n1,n2)=>{
      return n1+n2    
    }

    //以上代码只有一行,且return这行代码就可以简写为
    const sum=(n1,n2) => n1+n2
  • 箭头函数的形参个数 只有一个时也可以省略个数
  • 箭头函数不绑定this,箭头函数没有自己的this关键字,如果在箭头函数中使用this,this关键字将指向箭头函数定义位置中的this
  • 经典面试题
      var num=10
      let obj={
          num:1
          say:(){
              console.log(this.num)
          }
      }
     obj.say() //这里输出的是10
  • 具名的的箭头函数
     const gg=()=>{
        console.log(1)
     }
  • 顺口溜 删掉function关键字,加上一个胖箭头,没有参数加括号,一个参数可选择(加不加括号),多个参数逗号分隔(要加括号的)
  • 箭头函数不执行this 绑定
  • 不适用箭头函数的情况

    • 构造函数
    • 为原型添加方法的时候
    • 各种绑定事件
    • 在函数中使用arguments对象的时候
      1.作为构造函数,一个方法需要绑定到对象 
       const Person=function(name,points){
           this.name=name
           this.points=points;
       }
       const jelly=new Person('jelly',5);

      2.原型添加方法
       Person.prototype.updatePoints=function(){
           this.points++
           console.log(this.points)
       }

      3.事件
       const  button=document.querySelector('.zoom');
       button.addEventListener('click',function(){

       })

      4.需要使用arguments

      const sum =function(arguments){
        /*arguments不是个真正的数组 需要用Array.from 转换 或用扩展运算符[...arguments]来转换*/   
       return Array.from(arguments).reduce((prevSum,value)=>pervSum+value,0 )

       }
tips: 对象是不产生作用域,指向的s是全局window,所以箭头函数的this,指向的是window,所以这里输出的是10
5.剩余参数
  • 剩余参数语法允许我们将一个不定数量的参数表示为一个数组
    //定义个方法
    const sum =(...args)=>{
         let total=0;
         args.forEach(item=>{
            total+=itme 
         })
         return total
    }
    sum(10,20) //args里保存着10和20
    sum(10,20,30)//args里保存10,20,30
  • ...args,参数是一个数组的组合
  • 剩余参数和数据解构结合
    let ary1=['张三','李四','王五']
    let [s1,...s2]=ary1
    s1 //存着张三
    s2 //接收剩余参数成为个新数组,存着李四和王五
6.扩展运算符
  • 扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
    let ary=[1,2,3];
    ...ary //1,2,3 转为去掉括号的用逗号分隔的参数序列
    console.log(...ary) 1 2 3
  • 扩展运算符可用于合并数组,生成的是新数组
    let ary1=[1,2,3]
    let ary2=[4,5,6]
    ...ary1  //1,2,4 
    ...ary2  //4,5,6
    //第一种
    let ary3=[...ary1,...ary2]
    //第二种  -- push方法可以有多个参数
    ary3=ary1.push(...ary2)
  • 扩展运算符可将伪数组转为真正的数组,就可以使用数组的一些方法
    var Odivs=document.getElementsByTagName('div')
    console.log(Odivs) //伪数组 可迭代遍历但没有数组方法
    var ary=[...Odivs]
    ary.push('a')
    console.log(ary);
  • 扩展运算符是深拷贝,修改使用新生成的数组,不影响原来数组的值
  • 扩展运算符的应用实践
    1. //把二维数组扩展成对象数组
     [...array[1],...Array[1]] 
     输出
     [object,object]

    2. //可用来代替apply方法
     const fruit=['apple','bananas','pear'] 
     const newFruit=['orange','mongo']

     //用apply合并数组,apply后面跟着的参数是数组
     fruit.push.apply(fruit,newFruit) 
     //用扩展运算符来合并
     fruit.push(...newFruit) 
  • 扩展运算符适用于函数的传参
7 array.from() --数组的扩展方法
  • 可以把伪数组转为真正的数组
  • 方法还可以接收第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理的后的值放入返回的组数
例子1
var arrayLike={
    "0":"1",
    "1":"2",
    "length":2 
}
Array.from(arrayLike,item=>item*2)

例子2 
const todos=document.querySelectorAll('li');
const names=Array.from(todos,todo=>todo.textContent);
console.log(names)
  • 能把字符串也转换成数组
 const str='abc'
 console.log(Array.from(str))  [a,b,c]
8 array.find() --数组的扩展方法
  • 用于找出第一个符合条件的数组成员,如果没有找到返回undefined
let ary=[{
    id:1,
    name:'张三'
 },{
    id:2,
    name:'李四'
 }
]

let target= ary.find(item=> item.id==2 )
9 array.findIndex() --数组的扩展方法
  • 用于找出第一个符合条件的数组成员的位置,如果没有返回-1
let ary=[10,20,50]
const index= ary.findIndex((item,index)=>itme>15)
console.log(index)
10 array.includes() --数组的扩展方法
  • 表示某个数组是否包含某个元素
  • 字符串也可使用,可传入第二个参数表示第几个开始
 let ary=["a","b",c]
 ary.includes("a")
11 array.of() --数组的扩展方法

当前方法可以弥补 new Array 构造方法返回结果不一致问题。

/*当参数只有一位的时候,返回的是长度为1的数组 [undefined*1],而不是[1] 只有当参数是多个的情况下才会返回正确的数据*/
new Array(1)
array.of(1)  输出的是[1]
12 array.every() --数组的扩展方法

当遍历时遇到false时,就不执行了,返回false

13 模板字符串 --String的扩展方法
  • 作用就是字符串可以解析变量,用于字符串拼接 使用反引号
let name=`账上`
let sayHello =`hello${name}`
  • 模板字符串中可以换行,写的比较美观
let result={
    name:"Zhangsan",
    age:20
}

let html=`
 <div>
   <span>${result.name}</span>
    <span>${result.age}</span>
</div>
`
  • 模板字符串中可以调用函数、表达式等
  const fn=(){
    return '我是fn函数'
  }
  
 let html=`我是模板字符${fn()}`
 
  const template=`
  <div class="greet">
    <p> Hello </p>
  </div>
  `.trim()
  
  //模板字符串本身就是字符串,所以可以使用字符串方法
 
  • 模板字符串的实战应用
  function renderTodos(todos){
      return (
        `<ul>
            ${todos.map(todo=>`
              <li>
                 ${todo.name} ${todo.completed?'√':'X'}
              </li>`).join('')}
       </ul> `
      )
   }

 //map 返回的是数组 循环渲染有,所以用join 去除
  • 模板字符串的高级运用
const user='Mary';
const topic='learn to use markdown'
//模板字符串加方法
function highLight(strings,...values){
 //strings 输出的是:has commented on your topic
 //values 输出的是:user和topic
}
const sentence= hightlight `${user} has commented on your topic ${topic} `
  • 使用 DOMPurify.sanitize 来防止xss攻击,要引入 dompurify的purify.js
14 startsWith()、endsWith()

--String的扩展方法

  • startsWith():表示参数字符串是否在原字符串的头部,返回布尔值
  • endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
  • 大小写敏感的
  • 可传递第二个参数, 从第几个参数开始
let str='hello world';
str.startsWith('Hello') //true
str.endsWith('!') 、//true

//可传递第二个参数, 从第几个参数开始  
str.startsWith('Hello',6)
15.repeat --String的扩展方法
  • repeat方法表示将原字符串重复n次,返回一个新字符串
  • 可以应用于让字符串对齐
'x'.repeat(3) // "xxx"
'hello'.repeat(2) //hellohello
 const id  ='510300198007300366x'
 const fan ='I love Laravist.'
 function padder(string,length=25){
    return `${'',repeat(Math.max(length-string.length,0))}${string}`
 }

 console.log(padder(id))
 console.log(padder(fan))
16. for or循环遍历

支持数组、字符串等 但目前版本不支取对象的循环

Array.protype.frist=function() {
    return this[0]
}
const fruits=['Apple','Bannana','Orange','Mango'];
fruits.describe='My favorite fruits';

for(let index in fruits ){
   console.log(fruits[index] ) 会输出多余的值 
 }

for(let index of  fruits ){
   console.log(index ) 只输出数组内的值 可以 break
 }

//迭代器
for(let [index,fruit] of fruits.entries() ){
   console.log(index,fruit ) 只输出数组内的值 可以 break
 }
17.set 数据结构
  • es6 提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
const s=new Set()
s.size //看s的长度
  • es6 可以进行数组去重
const s3=new Set(["a","b","b"])
//用扩展运算符,变成用逗号分隔的
const arr=[...s3]
  • set 内置方法

    • add(value):添加某个值,返回Set结构本身
    • delete(value):删除某个值 返回一个布尔值,表示删除是否成功
    • has(value): 返回一个布尔值,表示该值是否为Set的成员
    • clear(value):清除所有成员,没有返回值
tips: set的方法可以使用链式调用
  • set 遍历
 const s5=new Set(['a','b','c'])
 s5.forEach(value=>{
     console.log(value)
 })
18. 递归
//接口返回数据结构--是个数组

0: {menu_id: 92, menu_name: "微信公众号", menu_fid: 0, menu_val: "92_wechat_publicnumber"}
1: {menu_id: 1, menu_name: "学校管理", menu_fid: 0, menu_val: "1_school"}
2: {menu_id: 2, menu_name: "教师管理", menu_fid: 0, menu_val: "2_psychologist"}
3: {menu_id: 3, menu_name: "学生管理", menu_fid: 0, menu_val: "3_counseling"}
4: {menu_id: 4, menu_name: "量表中心", menu_fid: 0, menu_val: "4_scale"}
5: {menu_id: 5, menu_name: "心理咨询", menu_fid: 0, menu_val: "5_advisory"}
6: {menu_id: 6, menu_name: "异常反馈", menu_fid: 0, menu_val: "6_abnormal"}
7: {menu_id: 7, menu_name: "活动管理", menu_fid: 0, menu_val: "7_activity"}
8: {menu_id: 8, menu_name: "在线求助", menu_fid: 0, menu_val: "8_help"}
9: {menu_id: 9, menu_name: "心理课堂", menu_fid: 0, menu_val: "9_classroom"}
10: {menu_id: 10, menu_name: "心理实验", menu_fid: 0, menu_val: "10_experiment"}
11: {menu_id: 11, menu_name: "订单管理", menu_fid: 0, menu_val: "11_order"}
12: {menu_id: 12, menu_name: "数据分析", menu_fid: 0, menu_val: "12_data"}
13: {menu_id: 14, menu_name: "学校列表", menu_fid: 1, menu_val: "14_school_list"}
14: {menu_id: 15, menu_name: "学校资讯", menu_fid: 1, menu_val: "15_information_list"}
15: {menu_id: 17, menu_name: "学校横幅", menu_fid: 1, menu_val: "17_schoolad_list"}
16: {menu_id: 18, menu_name: "老师列表", menu_fid: 2, menu_val: "18_psychologist_list"}
17: {menu_id: 19, menu_name: "老师导入", menu_fid: 2, menu_val: "19_teacher_import"}
18: {menu_id: 20, menu_name: "发送信息", menu_fid: 2, menu_val: "20_edit_notice"}
19: {menu_id: 21, menu_name: "学生列表", menu_fid: 3, menu_val: "21_counseling_list"}
20: {menu_id: 22, menu_name: "学生导入", menu_fid: 3, menu_val: "22_counseling_import"}
21: {menu_id: 23, menu_name: "发送信息", menu_fid: 3, menu_val: "23_edit_cou_notice"}
22: {menu_id: 24, menu_name: "用户统计", menu_fid: 3, menu_val: "24_user_count"}
23: {menu_id: 25, menu_name: "综合档案", menu_fid: 3, menu_val: "25_comprehensive_file"}
24: {menu_id: 26, menu_name: "量表分类", menu_fid: 4, menu_val: "26_scale_shape"}
25: {menu_id: 28, menu_name: "量表权限", menu_fid: 4, menu_val: "28_scale_rights"}
26: {menu_id: 29, menu_name: "测评查询", menu_fid: 4, menu_val: "29_assess_search"}


//根据fid生成带孩子的二级树形结构--只有二级就简单点

getJsonTree (data, fId) {
      let itemArr = [];
      data.forEach(item => {
        const { menu_id = 0, menu_fid = 0, menu_name = '', menu_val = '' } = item || {}
        if (menu_fid === fId) {
          let newNode = {
            id: menu_id,
            label: menu_name,
            value: menu_val,
            checkAll: false,
            checkedOptions: [],
            options: this.getJsonTree(data, menu_id) //第一个是0写死的id找不到父亲的,找到的都是当父亲的,第二个就是把自己的id当做是fid 去找它的孩子
          };
          itemArr.push(newNode);
        }
      })
      return itemArr;
    },

// 孩子的数组,特殊情况就用这个来代替 this.getJsonTree函数 (只限于二级)

    getChild (data, fId) {
      let itemArr = [];
      data.forEach(item => {
        const { menu_id = 0, menu_fid = 0, menu_name = '', menu_val = '' } = item || {}
        if (menu_fid === fId) {
          let newNode = {
            label: menu_name,
            value: menu_val,
          };
          itemArr.push(newNode);
        }
      })
      return itemArr;
    },
    
19. 对象字变量的扩展

es6 对象 变的更加强大

 const name='Lara'
 const age=2

 const keys=['name','age']
 const values=['lara',2]
 
 const laravist={
  [keys.shift()]:values.shift(),
  [keys.shift()]:values.shift(),
  [keys.shift()]:values.shift(),
 }
20. promise
  • 解决回调地狱
 const p=new Promise(reslove,reject)=>{
   setTimeout()=>{
     reject(Error('Error'))  
   }  
 })

 p.then(data=>{console.log(data)})
  .catch(err=>{console.log(err)})
  
tips: 在reject中使用Error返回错误信息时,使浏览器正确定位到是reject那行发出的错误信息,而不是catch那行。
  • Promise all 同时调用多个promise
const userPromise=new Promise((resolove,reject)=>{
  setTimeout(()=>{
      reslove(['mojom','vanpe'])
  },2000)    
})

const moviePromise=new Promise(()=>{
  setTimeout(()=>{
      reslove({name:"摔跤",rat:9.2})
  },500) 
})


 Promise.
  all([userPromise,moviePromise])
 .then(responses=>{
   console.log(responses)
 })
 .catch(responses=>{
  console.log(responses)
 })
tips: Promise all 当以上所有promise都正确执行时,才返回正确的,否则会被catch捕获。
  • Promise race 同时调用多个promise

当第一个调用的promise 正确执行时就在then中返回结果,不然就在catch中返回

21. Symbol
  • Symbol是js的第七种数据类型, 其他6种:Undefined、Null、Boolean、Number和String,复杂的数据类型Object
  • 主要用来标识唯一key,由于当前属性不能用普通的方法进行遍历,所以可以当私有属性,对于key值会重复的场景就可以使用Symbol来对其唯一标识
 const peter=Symbol('peter');
 const student=Symbol('student');
 //以下nina两个key值重复,所以用Symbol来标识
 const classRoom={
   [Symbol('lily')]:{grade:60,gender:'female'},
   [Symbol('nina')]:{grade:60,gender:'female'},
   [Symbol('nina')]:{grade:60,gender:'female'},
 }
 
//for 循环不能遍历
 for(let key of classRoom){
     console.log(key) //输出[]
 }

//另类遍历的方法
 const syms=Object.getOwnPropertySymbols(classRoom).map(sym>classRoom[sym])
 console.log(syms)

tips:classRoom[sym] 不能改成 classRoom.sym 这里会执行 classRoom['sym']但classRoom数据里并没有sym这个属性名

22. eslint 代码规范
  • eslint 会找当前目录的.eslintrc.js文件,如果找不到就往上级找
  • 全局使用某个对象 比如 Vue 可以使用,可不对eslint的规则进行配置
 /* globals Vue */
 
 .eslintrc.js 文件中
  globals: {
    Yx: true
  }

 
  • 禁用某条规则
 /* eslint-disable no-new */
  • 开启某条规则
 /* eslint-enable no-new */
  • eslint 可以使用外部的插件
 {
     "plugins":["markdown"]
 }
23 Reflect.ownKeys()

静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。

const object1 = {
  property1: 42,
  property2: 13
};

var array1 = [];
console.log(Reflect.ownKeys(object1));
// expected output: Array ["property1", "property2"]

console.log(Reflect.ownKeys(array1));
// expected output: Array ["length"]
24. parseInt

转化为整形

 //可以使用+也可隐士转化为数字
 +'243'
25. class
  • 方法名可以通过计算属性命名并可进行调用
  • 不能进行变量提示,必须先声明再引用
 let methodName = 'info'
  class User {
    constructor(name,age){
        this.name=name;
        this.age=age;
    }
    
    [methodName](){
         console.log(1)
      }
  }
  • 继承
  class student extends User {
    constructor(name,age){
        super(name);   
      /*super的作用及原理
       作用 :继承父类,等同于User.call(this,name)调用基类的构造函数
       原理:  student.prototype=new User()
       类的原型被改变了,但是类的原型的构造函数的也改变了,要指定构造函数为student
        student.prototype.constructor =student
      */
       this.age=age;
    }
  }
  • 扩展内置对象

为Array 添加自己的方法

class Movie extends Array {
  constructor(name,...items){
     super(...item)
     this.name=name
    }
    
   add(movie){
   //
    this.push(movie)
  }    
}

const movies=new Movie('favorite movies',
{name:'rr1',score:8.7},
{name:'rr2',score:99.7},
{name:'rr3',score:91.7}
)

movies.add() //添加内容
26. Iterator

遍历器(迭代器)

const colors=[1,2,3]
const iterator= colors[Symbol.iterator]()
iterator.next()

/*输出*/
Object{value:1,done:false }
iterator.next()

/*输出*/
Object{value:2,done:false }
iterator.next()

/*输出*/
Object{value:3,done:false }
iterator.next()

/*输出*/
Object{value:undefined,done:true}
tips:
当done为true时遍历就结束了,输出一个方法时有包含Iterator,就是遍历器了,比如数组的 keys,entries,
values
  • 遍历器内部原理
//实现一个Array.values
Array.prototype.values=function(){
 let i = 0;
 let items = this;
 return{
  //返回一个函数,形成闭包,可以进行累加
  next(){
    const done =i > = items.length;
    const value = done?undefined:items[i++]
    return{
        value,
        done
     }   
   }   
  }
}

for of 的运行机制

for(const itme of color){}
//of调用,colors[Symbol.iterator]() 这个属性。 并把里面的value值赋值给color
27. generator (可不学,直接看async、await)
  • generator是生成器,可以开始、暂停 ,最终生成的是个遍历器(迭代器);
function* listColors(){
   let i=0;
    yield i; //返回
   i++;
    yield i;
   i++;
    yield i;
 }

//生成了遍历器
const colors=listColors();

colors.next()
/*输出*/
Object{value:0,done:false}

colors.next()
/*输出*/
Object{value:1,done:false}

colors.next()
/*输出*/
Object{value:2,done:false}

colors.next()
/*输出*/
Object{value:undefined,done:true}

const colors=[1,2,3]
function* loop(repos){
 console.log(colors)
 for(const repo of repos){
    yield repo
 }
}
const repoGen=loop(repos)
  • 在项目中的实际应用(异步转同步)
//进行ajax方法
 function ajax(url){
   axios.get(url).then( res => 
   执行成功后再执行下一步
   userGen.next(res.data)
  )     
}
//生成器 
function* steps(){
  const users = yield ajax('https://api.github.com/users');
  const firstUser = yield ajax(`https://api.github.com/users/${users[0].login}`)
  const followers = yield ajax(firstUser.followers_url);
}
const userGen =steps()
userGen.next()
28.proxy
  • 添加、重写 对象上的默认方法,格式化默认值。
 const person = {name:'laravist',age:2000};
 const personHandle={
   //获取值
   get(target,key){
     //target:原目标; key:键值
     //把属性值都转换成大写
      return target[key].toUpperCase(); 
    }
   //设置值
   set(target,key,value){
     //去掉空格
     if(typeof value==='string'){
       target[key]=value.trim()
     }
    }
 }
 const personProxy = new Proxy(person,personHandle)
 personProxy.name=' codecasts '
 console.log(personProxy.name)
 // 输出:CODECASTS  --去去掉空格并转换成大写
  • 实际应用
// 安全挟持
const safeHandler = {
  set(target,key,value){
      //找相类似的键
      const likekey = Object.keys(target).find(k=>k.toLowerCase()===key.toLowerCase());
      //如果找到就不让其赋值
      if(!(key in target) && likekey ){
        throw new Error(` Oops! looks like we already have a property ${key} but with the case of ${likeKey}`)    
       }
   }  
}

const safetyProxy=new Proxy({id:2}, safeHandler); 
safetyProxy.ID=5  /*会报错,赋值已经被挟持了只要和id这个键值相类似的 比如 Id ID iD 都不让赋值*/ 
29.set
  • 唯一的数组
  • 不能通过索引值来获取值
 // 定义一个set
 const colors=new Set()
 colors.add(4)//添加元素
 colors.delete(4)//删除
 colors.has(4)//检验是否存在

 /*可以用正常的数组循环方式进行循环*/
 for(let color of colors ){
   console.log(color)
 }
 
 colors.forEach(item=>{
     console.log(item)
 })
 
  • 可通过扩展运算符转换成数组
 const colorsSet=new Set([1,2,3,4,4,4,4])
 const colorsArr=[...colorsSet]
 // 或者可以通过array.from() 来进行转换
30.WeakSet
  • 保存值的类型只能是对象
  • 没有set一样的clear方法,有自动清理功能、防止内存泄漏
  • 不能对他进行遍历
const {
  jelly:{name:'jelly',age:20},
  mary:{name:'mary',age:25}
} ={}

const weakPeople=new WeakSet([jelly,mary])
console.log(weakPeople)
mary=null
console.log(weakPeople) 

// mary 这个属性值就不见了, 如果用数组来存储,这个值还是存在的
  • 应用:单例属性,引用的追踪
31.map
  • 可以和数组一样进行循环和遍历
  • 可以和set一样使用相类似的api
 const people = new map();
 people.set('jelly',23)
 people.has('jelly')    //检验是否含有jelly这个值
 people.delect('jelly') //进行删除
 people.clear()全部删除
 //对 fruits 进行赋值 
 const fruits = new Map([['apple',6],['banana',5]])
 
 //用forEach和解构的方式来遍历map
 fruits.forEach([key,value]=>{
  console.log(key,value)   
 })
 //如果不用解构方式,他返回的值是一整个是数组
  • 应用场景: 存储对象的信息,而不单单是这个对象
32.weakMap
  • 和weakSet 类似不能进行循环,也没有clear方法,没有size
  • 保存的key值只能是对象
  • 防止内存泄漏
 const jelly = {name:'jelly'};
 const miffy = {name:'miffy'}

 const strong= new Map();
 const weak=new WeakMap();
 
 strong.set(jelly,'jelly is the best!')
 weak.set(miffy,'miffy is the 2nd best!')
未完待续

  1. 0-9
  2. A-Za-z0-9_
  3. trnvf

yaoxfly
431 声望28 粉丝