JS第四周知识总结

144 阅读7分钟

面向对象---封装、继承和多态

         1、封装(创建)--三种方式

                直接量方式 --适用于创建的对象较少时使用

                    语法: let obj={

                                    "属性名1":属性值,

                                    "属性名2":属性值,

                                    ....

                                    "方法名1":function(){

                                        操作;

                                    }

                                    "方法名2":function(){

                                    操作;

                                    }

                                    ...                      

        }

 

                预定义构造函数方式 --不推荐使用

                       语法:let obj=new Object()

                       添加属性和方法:

                               obj.属性名=属性值

                               obj.方法名=function(){

                                操作

                               }

                       特点:创建的是一个空对象,需要自己往里面添加属性和方法

                

                自定义构造函数方式--需要创建多个同类对象(属性名相同,属性值不同)

                    使用步骤:创建 function 名(形参a,形参b,形参c){

                                         this.形参a=形参a;

                                         this.形参b=形参b;

                                         this.形参c=形参c;

                    }

                             调用:let obj=new 名(实参a,实参b,实参c)

            访问对象的属性和方法

                访问属性: obj.属性名 或者  obj["属性名"]

                访问方法:  obj.方法名 或者  obj["方法名"]

                访问所有属性和方法:  使用for  in循环访问

                在对象里面使用自己的属性时:   this.属性名   

        

            问题:当多个对象有相同的方法时,每写一次方法就会占用内存,这就会降低网页的性能

            解决:利用对象的继承这一特点

        

        2、继承: 父对象的成员(属性和方法),子对象可以直接使

                 每个对象都有原型,我们只要为原型设置方法,子对象就可以使用其方法

             找父对象的方法:

                   方法一:对象名.proto

                      前提:必须有一个对象

 

                    方法二:构造函数名.prototype

                      目前学习的构造函数名:Array、String、Date、RegExp、Number、String、Boolean

                为原型添加方法:

                    语法:构造函数名.prototype.方法名=function(){

                        操作;

                    }

 

             继承中的笔试与面试题:

                  1、判断对象中的属性自有还是共有

                     公式:

                    if(obj.hasOwnProperty("属性名")){

                        属性名是自有属性

                    }

                    else{

                        if("属性名" in obj){

                            属性名是共有属性

                        }

                        else{

                            没有这个属性或方法

                        }

                    }

 

                    2、为原型或者浏览器添加它没有的方法

                    例:为老IE添加数组的indexof方法

                      步骤:1.判断是否是老IE

                            2.为其添加方法(直到方法的执行原理)

                      语法:

                    if(Array.prototype.indexOf===undefined){

                        Array.prototype.indexOf=function(key,starti){

                            starti===undefined&&(starti=0);

                            for(var i=starti;i<this.length;i++){

                                if(this[i]==key){ return i;

                                }

                            }

                            return -1;

                        }

                    }

 

                    3、修改和删除自有或共有属性

                       修改和删除自有属性和方法:

                           修改:

                           obj.属性名=属性值

                                 obj.方法名=function(){

                                    新操作;

                                 }

                            删除:

                            delete obj.属性名=属性值

                            delete obj.方法名

 

                        修改和删除共有属性和方法:

                            修改:

                            原型.属性名

                            原型.方法名=function(){

                                新操作;

                            }

                            删除:

                            delete 原型.属性名

                            delete 原型.方法名

                    4、判断引用数据类型

                      例:x是否是数组

                    方法一;语法:Array/Object/Date/RegExp.prototype.isPrototypeOf(type)  返回值为布尔值

 

                    方法二:语法:引用数据名 instanceof Array/Object/Date/RegExp  返回值为布尔值

 

                    方法三:语法:ES5 新增数组的判断 Array.isArray(引用数据名)  只能判断是否是数组  返回值为布尔值

 

                    方法四:固定语法:Object.prototype.toString.call/apply(x)  返回值为 [object 构造函数名]

 

                    5、实现自定义继承--设置对象的父对象

                         两个对象之间设置继承

                            语法:子对象.proto=父对象

                        

                         多个对象之间设置继承

                            语法:构造函数名.prototype=父对象

                            注意:一定要先设置父对象,然后在去创建对象

                    6、两链一包:

                         原型链:每个对象都有一个属性.proto,可以一层一层的找到每个人父亲,形成了一条链式结构

                         作用域链:以函数的EC的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构

                         闭包:想得到一个可以反复使用的局部变量的一种特殊的函数创建方式

                            

        3、多态:每一个原型都有它自己独有的方法,与其父对象的方法名相同但是操作不同

        

        

        4、ES6  class关键字--简化面向对象

               语法:

               class 类名 extends 老类名{

    constructor(name,speed,rl){

    super(name,speed);

    this.rl=rl;

}

                方法名(){

                    操作

                }

}

         

            注意:创建方法时,不用写function,直接写方法名(){操作}

    

    函数的闭包

       函数的执行原理:

          步骤:

               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会出栈,没人引用着AO,AO自动释放,局部变量也就释放;只会保存全局EC

        

        闭包:想得到一个可以反复使用的局部变量的一种特殊的函数创建方式

           使用:

                1、两个函数进行嵌套

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

    3、外层函数return出内层函数 (内层函数需要接住)

        4、内层函数在操作受保护的变量

            简单闭包:

                function out(){

                    let s=0;

                    return function(){

                        操作s;

                    }

                }

 

                let inner=out()

            

            闭包的优缺点:

                优点:防抖节流;变量不会改变

                缺点;每调用一次就会创建一个副本保存变量的值,会占用大量的内存空间,降低网页的性能

        

        使用场景:四个事件

                 1、elem.onmousemove

2、input.oninput

3、window.onresize

4、window.onscroll

        防抖节流公式:

             function fdjl(){

var timer=null;

return function(){

if(timer){

                            clearTimeout(timer);

                            timer=null;

                        }

timer=setTimeout(()=>{

操作;

},间隔毫秒数)

}

}

                let inner=fdjl()

 

正则表达式--定义字符串中字符出现规则的表达式

        使用场景:切割、替换和验证(用的最多)

        语法:/正则表达式/后缀

              后缀有;g(找全部) i(不区分大小写)

 

        1、最简单的正则表达式就式关键字符本身

            例:/hello/gi --就可以找到全部的hello

        

        2、备选字符集:/[备选字符集]/

              备选字符集中可以放入你想要的字符

            注意:一个中括号,只管一位。如果备选字符集的ASCII码是连续的可以简化为 开始字符-结束字符

              常用的字符集:

                一位数字:[0-9]

                一位字母:[A-Za-z]

                一位数字、字母、下划线:[0-9A-Za-z_]

                一位汉字:[\u4e00-\u9fa5]

                一位数字、字母、汉字、下划线:[0-9A-Za-z\u4e00-\u9fa5_]

 

        3、预定义字符集

                一位数字:\d

                一位数字、字母、下划线:\w

                一位空白字符:\s 什么叫空白字符:空格、制表符、换行

        

        4、量词--规定了一个字符集出现的次数

             有明确数量:

                字符集{n,m}:前边相邻的字符集,至少n个,最多m个

                字符集{n,}:前边相邻的字符集,至少n个

                字符集{n}:前边相邻的字符集,必须n个

 

             无明确数量:

                字符集?:前边相邻的字符集,可有可无,最多1个

                字符集*:前边相邻的字符集,可有可无,

                字符集+:前边相邻的字符集,至少一个,

 

        5、指定匹配位置

             开头:^

             结尾:$

             特殊:两者同时使用,前加^后加$,表示从头到尾要求完全匹配 - 用于做验证

 

        6、选择和分组--两则一般同时使用

             选择:在多个规则中选一个

             规则1|规则2

             分组:将多个字符集临时组成一组子规则

             (规则1|规则2)

            

        7、密码强度:用于判断字符串的复杂程度的

              预判公式:(?!字符集+$)

 

              常用密码规则:

                (?![0-9]+$) -> 不能全由数字组成

                (?![a-z]+$) ->不能全由小写字母组成

                (?![0-9a-z]+$) ->不能由数字和小写的组成,必须有其它字符

 

    字符串中支持正则的API

        1、切割

           语法:let arr=str.split("固定切割符"/RegExp)

 

        2、替换

           基础替换法:

                语法:str=str.replace(RegExp,"新内容");

                 缺点:只能替换成固定的内容

 

            高级替换法:

                语法:str=str.replace(RegExp,function(a,b,c){

                    return 判断a关键字的长度,从而返回不同的替换内容

                })

        

        3、格式化

            例:手机号的格式化

            关键:把你所需要显示的内容用组合括起来,这样就可以得到自己所需要的内容

            function format1() {

            let iphone = "13857642391";

            let reg = /^(\d{3})\d{4}(\d{4})$/

            iphone = iphone.replace(reg, function (a, b, c, d, e) {

            return ${b}****${c}

            })

            console.log(iphone)

            }

            format1()

    

    正则对象

        创建:

          直接量:let reg=/正则表达式/后缀

          构造函数:let reg=new RegExp("正则表达式","后缀")

 

        正则的API

           reg.test(user)  --放回是一个bool值

 

    this的指向:

        1、单个元素绑定事件this->这个元素

        2、多个元素绑定事件this->当前元素

        3、定时器中的this->window

        4、箭头函数中的this->外部对象

        5、函数中的this->谁在调用此方法,this就是谁

        6、构造函数之中this->当前正在创建的对象

 

    ES5 强制改变this的指向

       call/apply: 临时替换this的指向 (他们会立即执行函数,不会要调用)

            语法:

            1、函数名.call(借用的对象,实参,...) - 单独传入每个实参

            2、函数名.apply(借用的对象,arr) - 只能传入一个事件要求必须是一个数组

       

        bind: 永久的替换了this的指向   (需要自己调用)

            语法:let 新函数名=函数名.bind(永久对象,永久实参,...) //它相当于创建了一个与原函数功能一模一样的函数,并且更改了this的指向和可以设置永久的参数

 

        借用别人的方法的三个固定套路

            1、Math.max/min.apply(Math,arr) ===> Math.max/min(...arr)

            2、Object.prototype.toString.call/apply(arr)=="[object

            Array]"//toString不需要传入实参

            3、类数组转为普通数组:

                 1、老方式:接住=Array.prototype.slice.call/apply(类数组对象);

                 2、新方法:接住=Array.from(类数组对象)

 

    ES6 版本

         1、创建变量与常量 :let  const

         2、箭头函数:专门简化一切的匿名回调函数

            公式:function去掉,()和{}之间添加=>,如果形参只有一个,那么()省略,如果函数体只有一句话,那么{}省略,如果函数体只有一句话并且是return,那么{}和return都省略

         3、模版字符串

            语法:我的名字叫${变量名/对象名}

         4、 结构赋值--使用与数组和对象

             释义:解析结构再进行赋值 - 赋值的新方式

             执行原理:如果赋值符号,左右两边的结构一样,就会悄悄得解开/脱掉结构再一一进行赋值

              语法:

               类数组:let [a,b,c]=[1,2,3]

                  注意:变量名和值要一一对应

               类对象:let {a,b=默认值,c}={c:3,a:1,b:2}

                  注意:变量名和值要一一对应,但顺序可以不同

         5、新的循环 for of

             语法:for(let val of 数组名){

                操作;

             }

 

             缺点:只能遍历索引数组,不能遍历hash数组;没有提供过下标,意味着不能修改原数组

         6、Set 和Map 两种新的数据类型

            Set:类似于数组的一种数据格式 - 【去重数组,然后再转回数组】

              语法:[...new Set(arr)]

              ...扩展运算符,可以脱掉数组/对象的外套

 

 

            Map:类似于对象的一种数据格式

            let m=new Map();

             添加:m.set("键","值");

             获取:m.get("键");

             删除:m.delete("键");

             清空:m.clear();

             遍历:m.forEach(callback);

    

 

    取消绑定事件:

        1、如果你使用elem.on事件名=()=>{},那么写成:elem.on事件名=null; 可以取消事件绑定了

         

        2、如果你使用elem.addEventListener("事件名",callback); 那么写成

          elem.removeEventListener("事件名",callback); - 事件名和回调函数,【必须和添加时是一模一样的】

          注意:(只输出一次就取消绑定);要把回调函数进行封装,这样才能保证它们的地址值是一样的

 

 

    封装一个运动函数来设置css样式;

        语法:

        function animate(elem,obj){

            for(var i in obj){

                elem.style[i]=obj[i]

            }

        }

 

    插件文件的使用--百度

      例1:动画文件的使用步骤:

            1、打开百度:搜索animate.css得到网址 animate.style/        

            2、下载文件

            3、引入此文件

            4、挑选你喜欢的动画,把class放到你需要的元素上

            5、并且要设置上animation-duration: 1s;执行时长

            6、还需要根据不同的动画,设置不同的初始效果,才会好看

        

        例2:地图插件的使用步骤:

            1、打开百度:搜索:百度/高德地图开放平台,进入

            2、注册/登录百度账号

            3、拉到最下面 - 注册成为开发者,跳转到控制台

            4、创建应用 - 应用名称你随便,应用类型浏览器端,白名单写一个*,实名认证一下

            5、恭喜你得到了密钥 - 成功了一大半了

            6、鼠标放到导航条上开放文档 -> javascript API -> 示例DEMO -> 挑选你喜欢的地图,复制到你的项目之中

            7、修改JS代码、在线查询经纬度

            8、注意:再百度地图某次升级过后,出现了GL地图和普通版地图,两者不可以混搭使用,只要是GL都可以混搭使用