es5、es6、es7知识点的归纳与总结(笔记)

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(){};
  1. 函数表达式(匿名函数)
var fun =function(){
    
}
  1. 利用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()
    
  1. 对象的方法

this指向o

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

this 指向实例对象

function Star(){};

new Star();
  1. 绑定事件函数

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

//点击了按钮就可以调用这个函数
btn.onclick=function(){};
  1. 定时器函数
    this指向的是window

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

setInterval(function(){     
},1000);
  1. 立即执行函数

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指向

  • 区别点:

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

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

15. 严格模式

  • 作用:

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

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

  1. 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以外的字符,相当于[^0-9]
\w 匹配任意的字母、数字、和下划线,相当于[A-Za-z0-9_]
\W 匹配任意的字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]
\s 匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
\S 匹配非空格(相当于[^\t\r\n\v\f]
  • 正则里还可以用 | 表示或者的意思
//座机号码验证 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攻击,要引入 dompurifypurify.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!')

未完待续 ~~~~
发布了4 篇原创文章 · 获赞 65 · 访问量 4647

猜你喜欢

转载自blog.csdn.net/u010716530/article/details/103681316