第四周学习

70 阅读9分钟

day14

事件取消绑定

1.如果使用的  elem.on事件名=()=>{}  ,那么写成   elem.on事件名=null  ,就可以取消绑定
2.如果使用的  elem.addEventListener("事件名",callback)  那么写成elem.removeEventListener("事件名",callback)

this的指向

1.单个元素绑定事件this ---> 这个元素
2.多个元素绑定事件this ---> 当前元素
3.箭头函数中this      --->  外部对象
4.函数中的this        --->  当前正在调用函数的这个对象
5.定时器中的this      --->  window

ES5强制改变this的指向 笔试面试

call/apply:临时的替换了函数中的this --借用
   语法:
       函数名.call(借用的对象,实参...)- 单独传入每个实参
       函数名.apply(借用的对象,arr)-只能传入一个实参 要求必须是一个数组 apply具有打散数组的功能
   强调:
       call/apply相当于立刻调用函数,立即执行的

bind:永久的替换了函数中的this
    三件事
        创建了一个和原函数功能完全相同的新函数
        将新函数的this永久绑定为了指定对象,无法再次被call/apply
        将新函数的部分参数永久固定
    
    语法
        var 新函数名 = 函数名.bind(永久对象,永久实参)不是立刻执行,需要调用

三个固定套路
    最大值、最小值
        Math.max/min/apply(Math,arr) ==> Math.max/min(...arr)
    判断是不是数组
        Object.prototype.toString.call/apply(arr) == "[object Array]"
    类数组转为普通数组
        var arr = Array.prototype.slice.call/apply(类数组对象)
        var arr = Array.from(类数组对象)

ES6

  let const 箭头函数
  模板字符串直接识别变量,不再需要+运算符进行拼接,实现了一个简单的js环境,甚至支持在里面做运算写API
  `你的名字叫${name}`
  
  解构赋值
      解析结构再进行赋值,赋值的新方式,并且得到了增强,如果赋值符号左右两边的结构一样,就会悄悄打开结构再一一赋值
      语法
          类似数组的解构赋值
              let[a,b,c]=[1,2,3]
          类似对象的解构赋值
              let {a,b="默认值",c}={c:1,a:2,b:3}
          调用函数,传递实参的顺序其实无所谓
              function zwjs ({name="1",age,hobby})}{
                  return`我的名字叫${name},今年${age},喜欢${hobby}`
              }
              zwjs({age:18,hobby:"js"})
          函数的返回结果可以是多个
              function f1(){
                  var a =1; var b=2;
                  return [a,b];
              }
              var[a,b]=f1()
 新的循环
     for(var val of 数组名){ }
     缺点:没有提供下标 不能修改原数组
           只能遍历索引数组,不能遍历hash数组,不能遍历对象
 set和map
     1.set 可以用来去重数组
         [...new set(arr)]
     map
         var map = new Map()

day15

正则表达式

定义字符串出现规则的表达式
何时使用
    切割、替换、验证
如何使用
    /正则表达式/
    简单的正则表达式就是关键字 /no/后缀
        后缀 g-->找全部     i-->忽略大小写
    
    备选字符集 /^[备选字符集]$/
        强调
            一个中括号只管一维字符
            正则表达式默认就不管后续了,做验证希望从头到尾完全匹配,这时需要加上^和$
        特殊
            如果备选字符集中ascii码是连续的,可以用-省略掉中间部分[0-9][A-Z][a-z]
   
    预定义字符集
        一位数字 \d
        一位数字、字母、下划线 \w
        一位空白字符  \s
        一位除了换行外的任意字符 .
        
   量词  规定了一个字符集出现的次数
       有明确的数量
           {n,m} 前面相邻的字符集 至少n个 做多m个
           {n,}  前面相邻的字符集 至少n个 多了不限
           {n}   前面相邻的字符集 只能n个
       无明确数量
           ? 可有可无 最多一个
           * 可有可无 多了不限
           + 至少一个 多了不限
  
  选择和分组
      选择 在多个规则中选一个
          规则1|规则2
      分组 将多个字符集临时组成一个子规则
          (规则1|规则2)
  
  匹配指定位置
      开头 ^
      结尾 $
      特殊:两者同时使用,前加^ 后加$表示从头到尾 完全匹配
  
  密码强度
      预判公式
          (?![0-9]+$) ---> 不能全由数字组成
          (?![0-9a-z]+$) ---> 不能全由数字组成、小写字母组成,也不能全由数字和小写字母的组合组成
 
  字符串中支持正则的API
      切割
          var arr = str.split("正则表达式")
      替换
          基础替换法
              str = str.replace(正则表达式,"新内容")
          高级替换法
              str = str.replace(正则表达式,function(a,b,c){
                  a --->匹配到的关键字
                  b --->正则匹配到的关键字的下标
                  c ---> 原字符串
              })
     格式化
         var str = "123456789123456789"
         var reg = /\d{d}(\d{4})(\d{2})(\d{2})\d{4}/
         id = if.replace(reg,function(a,b,c,d,e,f){
             a --->匹配到的关键字
             b --->第一个分组
             c --->第一个分组
             d --->第一个分组
             e --->下标
             f --->原数组
         })
正则对象
    创建:
        直接量 var reg = /正则表达式/后缀
        构造函数 var reg = new RegExp("正则表达式","后缀")
    API
        var bool = reg.test("输入的内容")

day16

animate.css
    https://animate.style/
    挑选喜欢的动画,把class放在需要的元素上
    设置animation-duration:1s(想要的时间数)

day17

Object对象
    对象具有属性和方法,都是预定义好的
    面向对象
        开发方式
            面向过程:过程 - 开始 -> 结束,
            面向对象:
                何时使用,操作都封装在一个对象中
                为什么使用 代码复用性
   封装/创建/定义 封装自定义对象3种
       直接量方式
           var obj ={
               "属性名":属性值,
               "方法名":function(){}
           }
      强调
          其实属性名和方法名的""可以不加
          访问对象的属性和方法
              obj.属性名 === obj["属性名"]
              obj.方法名() == obj["方法名"]
          访问不到的属性会返回undefined
          可以随时的添加新的属性和方法
              obj.属性名=新值;
              obj。方法名=function(){}
     遍历对象
         使用 for in 循环,通过obj[i]拿到值
     在对象的方法里使用对象的属性 ---->this.属性名

this 指向
    单个元素绑定事件 ---> 这个元素
    多个元素绑定事件 ---> 当前元素
    定时器中的this ---> window
    箭头函数中的this ---> 外部对象
    函数中的this ---> 当前调用函数的
    钩子函数中的this ---> 当前正在创建的对象

预定义构造函数方式
    var obj = new Object();
    obj.属性名= 新值
    obj.方法名=function(){}
   
自定义构造函数方式
    创建自定义构造函数
        function 类名(v1,v2,v3){
            this.属性名1=v1;
            this.属性名2=v2;
            this.属性名3=v3;
        }
    调用构造函数创建对象
        var obj = new 类型(实参)
优点
    便于维护,创建多个对象时方便

继承 父对象的成员,子对象可以直接使用
    提高代码的复用性
    多个对象公用的属性和方法集中到父对象中
    
    如何找到原型对象,保存一类子对象共有属性和方法
        对象名.__proto__;
        构造函数名.prototype
面试题
    两链一包 作用域链 原型链 闭包
    

day17

面向对象(笔试题)
    判读是自有还是共有
        判断自有 obj.hasOwnPrototype("属性名")
            ture -> 自有属性
            false -> 不是自有属性
        判断共有
            if(obj.hasOwnPrototype("属性名")==false){
                自有;
            }else{
                if("属性名" in obj){
                    共有;
                }else{
                    没有;
                }
            }
    
    修改和删除 自有和共有
        自有
            obj.属性名=新属性值
            delete obj.属性名
        共有
            原型.属性名=新属性值
            delete 原型.属性名
   
   如何为老IE的数组添加indexOf()方法
       if(Array.prototype.indexOf===undefined){
           Array.prototype.indexOf = function(key,start){
               start === undefined &&(start=0);
               for(var i =start;i<kei.length;i++){
                   if(this[i]==key){
                       return i;
                   }
               }
               return -1;
           }
       }
 
  如何判断X是不是一个数组
      判断X是不是继承自Array.prototype
          Array.prototype.isPrototypeOf(x)
              true ---> 数组
              false --->不是数组
      
      判断X是不是由Array这个构造函数创建
          x instance of Array
              true ---> 数组
              false --->不是数组
      
      Array.isArray(x) 只能数组可用
           true ---> 数组
           false --->不是数组
      
      输出 对象的字符串 的形式
          Object.Prototype.toString.call(x) === "[object Array]"
              true ---> 数组
              false --->不是数组
             
  实现自定义继承
      两个对象之间设置继承
          子对象.__proto__ = 父对象
      多个对象之间设置继承
          构造函数名.prototype = 父对象
          应该在开始创建对象之前就设置好继承关系
           
  ES6 - class关键字:简化面向对象(封装、继承、多态)
        class 类名 extends 老类名{
                constructor(name,speed,rl){//放在constructor里面得都是自有属性
                        super(name,speed);//调用继承的老类的constructor函数
                        this.rl=rl;
                }//放在constructor外面得都是共有方法
                //还会继承到老类所有的API,也可以在此处添加属于自己的新的API
        }

        var obj=new 类名(实参,...)
       
Function - 闭包:
    作用域:21、全局:随处可用,可以反复使用,缺点:容易被污染

        2、函数:只能在函数调用时内部可用,不会被污染,缺点:一次性的,使用完就会释放的。

    函数的执行原理:
        1、程序加载时:
                创建执行环境栈(ECS):保存函数调用顺序的数组
                首先压入全局执行环境(全局EC)
                全局EC引用着全局对象window	
                window种保存着我们的全局变量

        2、定义函数时
                创建函数对象:封装代码段
                在函数对象中有一个scope(作用域)属性:记录着函数来自的作用域是哪里
                全局函数的scope都是window

        3、调用前
                在执行环境栈(ECS)压入新的EC(函数的EC)
                创建出活动对象(AO):保存着本次函数调用时用到的局部变量
                在函数的EC中有一个scope chain(作用域链)属性引用着AO
                AO还有parent属性是函数的scope引用着的对象

        4、调用时:
                正是因为有了前面三步,才会带来变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错

        5、调用完:
                函数的EC会出栈,没人引用着AOAO自动释放,局部变量也就释放了

闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊
        何时使用:希望保护一个可以【反复使用的局部变量】- 私有化变量
        如何使用:
                1、两个函数进行嵌套
                2、外层函数创建出受保护的变量
                3、外层函数return出内层函数
                4、内层函数在操作受保护的变量

        强调:
                1、判断是不是闭包:有没有两个函数嵌套,返回内层函数,内层函数再操作受保护的变量
                2、外层函数调用了几次,就创建了几个闭包,受保护的变量就有了几个副本
                3、同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量

        缺点:受保护的变量,永远都不会被释放,使用过多,会导致内存泄漏 - 闪退,不可多用!
        
四个事件需要防抖节流 - 共同:触发的飞快,但是我们不需要飞快的修改DOM树!
        1、elem.onmousemove
        2、input.oninput 
        3window.onresize
        4window.onscroll
        
        防抖节流公式:
            function fdjl(){
                    var timer=null;
                    return function(){
                        if(timer){clearTimeout(timer);timer=null;}
                        timer=setTimeout(()=>{
                                操作;
                        },间隔毫秒数)
                    }
            }
            var inner=fdjl()

总结:两链一包:
        1、作用域链:以函数的EC的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构
            作用:查找变量,来带了变量的使用规则:优先使用局部的,局部没有找全局,全局没有就报错
        2、原型链:每个对象都有一个属性.__proto__,可以一层一层的找到每个人父亲,形成了一条链式结构
            作用:找共有属性和共有方法的,哪怕自己没有会悄悄的向上查找,如果最顶层也没有才会报错最顶层是Object的原型,甚至上面放着我们眼熟的API - toString,怪不得人人都可以使用
        3、闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊
             作用:专门用于防抖节流