我的JS第四周

162 阅读6分钟

1、animate.css文件是一个动画库

如何使用:

1、打开:animate.style/

2、下载

3、引入animate文件

4、挑选,将class放在使用动画的元素上

5、设置上animate-duration:几秒钟,时长,如果不想自己设置,提供了"animate_animated"只能1s

6、设置初始效果

swiper插件

1、搜索swiper

2、点击swiper按钮

3、点击导航条上的在线演示

4、挑选一个,右键查看源代码

封装运动(动画)函数

function animate(selector,obj){
    let elem=document.querySelector(selector);
    for(let i in obj){
        elem.style[i]=obj[i]
    }
}

高德/百度地图:

1、打开百度搜索:百度地图开放平台

2、注册/登录

3、拉到最下面,注册成为开发者

4、应用管理->我的应用->创建应用->用户名->选择浏览器端->0.0.0.0/0

5、得到密钥

6、导航栏->开发文档->JSapi->示例demo->挑选复制->修改css/js代码,查询在线经纬度(百度地图拾取坐标系统)

7、注意:GL只能和GL混搭,普通版只能和普通版混搭

8、VScode只能使用live server打开

object:封装、继承、多态

1、面向对象:任何操作都要封装在一个对象之中

面对过程:先干什么,再干什么,最后干什么

2、封装:

1、直接量方式:
let obj={
    "属性名":属性值,
    "方法名":function(){}
}

2、访问对象的属性和方法:
对象名.属性名===对象名["属性名"]
对象名.方法名===对象名["方法名"]

3、访问到不存在的属性返回的是undefined

4、添加新属性、方法:
obj.属性名=属性值
obj.方法名=function(){}

5、必须使用for in循环进行遍历且obj[i]才能够拿到,obj.i只能得到undefined

6、如果要在对象的方法之中使用属性,必须写this.属性名
难点:this的指向,在自定义构造函数的this->当前正在创建的对象

预定义构造函数

let obj=bew Object;//空对象
添加:
    obj.属性名=属性值
    obj.方法名=function(){}
    

以上两种方式一次只能创建一个

自定义构造函数方式

  1、创建自定义构造函数
  function 类名(name,age,hobby){
      this.name=name;
      this.age=age;
      this.hobby=hobby;
  }
  2、调用构造函数创建对象
  let obj=new 类名(实参,...)

继承

父对象的成员(属性和方法),子对象可以直接使用

为什么要继承:代码重用!提高代码的复用性

何时继承:只要多个子对象共用的属性和方法,都要集中定义在父对象

1、如何找到原型对象:

1、对象名:__proto__;
2、构造函数:.prototype

2、面试题:两链一包:作用域和原型链和闭包

每个对象都有一个属性__proto__,可以一层一层的找到每个人的父亲,形成一条链式结构,我们称之为原型链,可以找到都对象的成员(属性和方法),

作用:找到共有属性和共有方法,自己没有悄悄往上找

最顶层的是Object的原型,上面有一个toString()所有人都可以使用

继承的笔试题:

1、判断是自有还是共有:

 1、判断自有:obj.hasOwnproperty("属性名")
 结果为true,则为自有属性,结果为false就是有两种结果,一种是没有,一种是共有
 
2、判断共有:
if(obj.hasOwnproperty("属性名")==false "属性名" in obj)
//in关键字,会自动地查找整条原型链上的属性,true则是有,false就是没有
}else{ //没有}
完整公式:
if(obj.hasOwnproperty("属性名")){
    console.log("自有")
}else{
    if("属性名" in obj){
        console.log("共有")
    }else{
        console.log("没有")
    }
}

2、修改和删除:自有和共有

自有:
    改:obj.属性名=新值
    删:delete obj.属性名
 共有:**一定要找到原型链进行修改**
 改:原型.属性名=新值//不能直接修改,会在本地增加一个同名属性
 删:delete 原型.属性名

3、如何为老IE添加indexOf方法(为XX添加XX方法)

if(Array.prototype.indexOf===undefined){
    Array.prototype.indexOf=function(key,starti){
        starti===undefined&&(starti=0)
        for(i=starti;i<this.length;i++){
        if(this.[i]==key){
            returni
        }
        }return -1
    }
}

4、如何x是不是一个数组:四种方式,不要用typeof,无法查找引用类型

1、判断x是不是继承自Array.prototype
Array.prototype.isPrototype(x)
结果truefalse说明不是数组
注:可判断其他类型,把Array换成(Date,RegExp)就行
2、判断x是不是Array这个构造函数创建的
    x instanceof Array
 同上true为数组,一样可把Array换成其他判断
3Array.isArray(x) ES-5提供,只能判断数组,不支持其他
4、输出【对象的字符串】形式
    在Object上保存着最原始的toString()他的输出结果是:[object 构造函数名]
多态:子对象觉得父对象的成员不好用,就在本地定义了一个同名函数,覆盖了父对象的成员
借用的套路:Object.prototype.toString.call/apply(x)===[object Array]

5、实现自定义的继承:

①两个对象之间继承

  子对象.__proto__=父对象

②批量设置继承

  构造函数名.prototype=父对象
  注:创建对象之前设置好继承关系

Es-6的class关键字:简化面向对象

 class 类名 extends 老类{
     constructor(name,speed,rl){//constructor里面的就是自有属性
     super(name,speed);
     this.rl=rl
     }
     //写上共有方法,没有就会继承老类,也可以自己写,并且不会覆盖到爷爷,就形成了多态
 }

3、function:作用域链&闭包
①程序加载时 :

创建执行环境栈(ECS):保存函数的调用顺序的数组

首先压入全局环境(全局EC)

全局EC引用着全局对象window

window保存着我们的全局变量

②定义函数时:

创建函数对象:封装着代码段

在函数对象中有一个scope(作用域)的属性:记录着函数来自的作用域是哪些

全局函数的scope都是window

③调用前:

在执行环境栈(ECS)中压入新的EC(函数EC)

创建出活动对象(AO):保存着本次函数调用时用到的局部变量

在函数的EC中有一个scope chain(作用域链)属性引用着AO

AO还有parent属性是函数的scope引用着的对象

④调用时:

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

⑤调用完:

函数的EC会出栈,没人引用着AO,AO自动释放,局部变量释放

闭包:希望保护一个可以反复使用的局部变量的一种词法结构,其实还是一个函数,只是写法比较特殊

使用:

①两个函数进行嵌套

②外层函数创建出受保护的变量

③外层函数return出内层函数

④内层函数操作受保护的变量

强调:

①判断是不是闭包,有没有两个函数进行嵌套,返回内层函数,内层函数在操作受保护的变量

②外层函数调用几次就会创建几个闭包,受保护的变量就会多几个副本

③同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量

缺点:受保护的变量是不会被释放的,使用过多会内存泄漏-闪退

使用场景:防抖节流

 五个事件:
 1、elem.onmousemove
 2/input.oninput
 3、elem.onclick
 4window.onscroll
 5window.onresize
 固定公式:
 function fdjl(){
     var timer=null;
     return function(){
         if(!=null){
             clearTimeout(timer)
         }
         timer=setTimeout(()=>{
             操作
         },1000)
     }
 }

总结:

原型链:每个对象都有一个属性__proto__,可以一层一层的找到每个人的父亲,形成一条链式结构//查询共有属性和方法

作用域链:以函数的EC的scope chain为起点,经过AO逐级引用,形成的链式结构//查找变量,带来了变量的使用规则

闭包:希望保护一个可以反复使用的局部变量//用于防抖节流

ES5-保护对象:保护对象的属性和方法

1、对象的每个属性都有四大方法:

 value:xxx//实际保存的值的地方
 writable:true//开关,控制着这个属性是否能修改
 enumerable:true//开关,是否可以被for in循环
 configurable:true//控制这个属性是否可以删除

修改四大属性:

 1、Object.defineProperty(对象名,"属性名",{
     writable:true/false,
     enumerable:true/false,
     configurable:true/false
     
 })一次只能保护一个

2、

 Object.defineProperties(对象名,{
     "属性名":{
         四大特性...
     }
 })只调用一次,不能防止添加

四大特性:其实应该叫做六大特性-可以帮助我们做出动态数据

 Object.defineProperty(对象名,"属性名",{
 get:()=>{
     获取到的数据会被拦截
 }
 set:(V)=>{
     这个v就是拦截的数据,设置的数据会被拦截
 }
 })

2、对象的深拷贝和浅拷贝

1、浅拷贝:利用按值传递

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

2、深拷贝:两者互不影响

let obj1={"name":"obj1"}
let obj2={...obj1}
后端穿衣服:let jsonTxt=JSON.stringify(jsonobj)
前端脱衣服:let jsonobj=JSON.parse(jsonTxt)//eval("("+jsonTxt+")")

Error

目的:快速找到错误;防用户

2、浏览器自带的四种错误类型

 语法错误:syntax Error-符号/语法错误
 引用错误:ReferenceError-没有创建就在使用
 类型错误:Type Error-不是你的方法,你却调用使用了,常见于用undefinednull去操作
 范围错误:RangeError-num.toFixed(d)-d只能取值到0-100之间

3、报错也能让后续代码执行

  try{
      可能出错的代码
  }catch(err){
      发生错误执行的代码;err-形参,黑色的错误
  }
//性能巨差不如用分支结构代替

4、抛出自定义错误:

  throw new Error("自定义错误消息")

柯里化函数

   function(a){
       return function(b){
           return function(c){
               console.log(a+b+c);
           }
       }
   }
   add(3)(5)(7)

匿名函数

①自调:只执行一次,函数中没有用的变量会自动释放,可以用于代替全局代码的写法,绑定好的事件是不会自动释放的

   (function(){操作})()

②回调:只要不是自调的匿名函数就是回调函数,一切的回调函数都可以简化成箭头函数

设计模式:

单例模式:也称之为单体模式,保证一个类仅有一个实例对象创建,并且提供了一个访问他的全局访问点:new Vue一个页面一次

做简单的单例:利用ES-6中不允许let重复声明,但是不太推荐:①会污染命名空间②维护不易管控

观察者模式:也称呼订阅-开发模式,是bus总线的底层

事件轮询

1、宏任务:不会卡住单线程应用,可以让后续代码先走

①定时器:setInterval和setTimeout

②AJAX也是一个异步宏任务

2、微任务:ES6提供了Promis对象,可控制异步代码的顺序

function  xx(resolve){
    setInterval(()=>{
        .....
        resolve();
    },1000)
}
function xx(resolve){
    return new Promise(function(resolve)){
        setInterval((c)=>{
            ...
            resolve()
        },xx)
    }
}

new Promise(ajax1).then(ajax).then()...

要想连续执行then要在操作中return Promise,要想执行后面,要加上resolve()放行