• JS高级


    安装

     安装visual studio code

     安装visual studio code插件

    一、正则表达式

    正则表达式概述(Regular Expression)

    专门描述字符串中字符出现规则的表达式。

    1.正则表达式可用于:

    1).验证字符串格式

    2).查找敏感词

    2.字符集

    简写:如果[]中部分备选字符连续,可用-省略中间字符

    比如:[0123456789]可简写为[0-9]

    要匹配一位小写字母:[a-z]

    要匹配一位字母[A-Za-z]

    匹配一位字符或者数字:[0-9A-Za-z]

    要匹配一位汉字:[u4e00-u9fa5]

    3.预定义字符集

    正则表达语法为四种常用的字符集定义了最简化写法,称为预定义字符集。

     

      

    二. String中的正则API

     1.查找:

      1). 查找一个固定的关键词出现的位置:

       var i=str.indexOf("关键词"[,starti])

        在str中从starti位置开始找下一个"关键词"的位置

        如果省略starti,则默认从0位置开始向后找

        返回: “关键词”第一字所处位置的下标

          如果找不到,返回-1

       问题: 只支持查找一个固定不变的关键词

     

     2. 用正则表达式查找一个关键词的位置:

       var i=str.search(/正则/i);

        在str中查找符合"正则"要求的敏感词

        返回值: 关键词的位置

          如果找不到,返回-1

     问题: 正则默认区分大小的!

       解决: 在第2个/后加后缀i,表示ignore,意为:忽略大小写

       问题: 只能获得关键词的位置,不能获得关键词的内容

       解决: match

      3. match:

       1). 查找一个关键词的内容和位置:

        var arr=str.match(/正则/i);

        在str中查找符合"正则"要求的敏感词的内容和位置

        返回值: 数组arr:[ "0":"关键词", "index": 下标i ]

            如果找不到: 返回null

        问题: 只能查找第一个关键词,不能查找更多关键词

       2). 查找所有关键词的内容:

        var arr=str.match(/正则/ig)  //g  global 全局/全部

        返回值: 保存多个关键词内容的数组

        问题: 只能找到内容,无法获得位置

     4. 即获得每个关键词的内容,又获得每个关键词的位置

       reg.exec()

    5. 替换: 将找到的关键词替换为指定的新值

      2种方式:

      1). 简单替换: 将所有关键词替换为统一的新值

        str=str.replace(/正则/ig,"新值")

         查找str中所有符合“正则”要求的关键词,都替换为统一的新值。

         问题: 所有字符串API都无权修改原字符串,只能返回新字符串。

         解决: 如果希望替换原字符串,就必须自己手动赋值回原变量中

     衍生操作: 删除关键字: 其实将关键词替换为""

      2). 高级替换: 根据每次找到的关键词不同,动态选择要替换的新值

        str=str.replace(/正则/ig, function(kword){

          根据kword的不同,动态生成新值

              return 新值

        })

     查找str中所有符合“正则”要求的关键词

        每找到一个关键词,就自动调用一次回调函数

          每次调用回调函数时自动传入本次找到的关键词给kword

          回调函数中根据每次收到kword的不同,动态返回新值给replace函数

        replace函数自动将回调函数返回的新值,替换到字符串原关键词位置。

    6. 切割: 将一个字符串,按指定的切割符,切割成多段子字符串

      2种:

      1). 简单切割: 切割符是固定的

        var arr=str.split("切割符")

         将str按指定的"切割符",切割为多段子字符串,保存在数组arr中

        固定套路: 打散字符串为字符数组

         var chars=str.split("")

      2). 复杂切割: 切割符不是固定的

        var arr=str.split(/正则/i)

     

    三. RegExp对象:

    1.什么是:

    保存一条正则表达式,并提供了用正则表达式执行验证和查找的API 的对象

     2.何时使用:

    只要在程序中保存和使用正则表达式,都要用RegExp对象

    3. 如何使用:

      创建:

       1). 用/创建(直接量): var reg=/正则/ig

         何时: 如果正则表达式是固定不变的

       2). 用new创建: var reg=new RegExp("正则","ig")

         何时: 如果正则表达式需要在运行时才动态生成时

     

      4.API:

      1). 验证:

       var bool=reg.test(str)

        用正则reg,检测str是否符合正则的格式要求

        问题: 正则默认只要找到部分内容与正则匹配就返回true

        解决: 必须从头到尾完整匹配,才返回true

             只要验证,必须前加^后加$,表示从头到尾的意思

      2). 查找:

       获取每个关键词的内容和位置:

       var arr=reg.exec(str)

       在str中查找下一个符合reg要求的关键词的内容和位置

       如果反复调用reg.exec(),则自动会向后找下一个。

      找不到时返回null

       返回值: arr:[ "0":"关键词", "index": 关键词位置 ]

     

    总结:

     a).验证只能用test
    b).查找一个固定关键词indexOf
    c).如果关键词变化用search

    d).既找内容有找位置用match

    e).找所有关键词内容和位置用exec

    三. Function

    1.什么是函数

     什么是函数: 封装一项任务的步骤清单代码段的对象,再起一个名字。

     为什么: 重用!

     何时: 只要一段代码可能被反复使用,都要创建函数。

    2.如何使用

    1).创建函数:

    JavaScript中创建函数的三种方式

    a).使用function关键字声明方式创建命名函数

      

    b).使用直接量赋值方式创建命名函数 

    var  函数名=function(形参1,形参2,...){

    函数体;

    return 返回值;

    }

     

     

     

    c).使用Function构造方法创建函数

     3.重载(overload)

     1). 什么是: 相同函数名,不同形参列表的多个函数,在调用时,可自动根据传入实参的不同,选择对应的函数调用

      2).为什么: 减少函数名的数量,减轻维护的负担

      3).何时用: 一件事,可能根据传入的参数不同,执行不同的操作时

      4).如何:

       问题: js语法默认不支持重载

         因为js不允许多个同名函数同时存在

           如果存在,最后一个函数会覆盖之前所有

       解决: 使用arguments对象变通实现

         什么是arguments对象: 每个函数内自动创建的,准备接受所有传入函数的实参的 类数组对象

           自动创建: 不用自己创建,就可直接使用

           接受所有实参:

           类数组对象: 长的像数组的对象

            vs 数组: 相同: 1. 下标  2. length  3. 遍历

                    不同: 类型不同,API不通用 

         何时: 只要不确定将来传入函数的参数个数时,就不定义形参列表,而是用arguments接住所有的实参值。

     

     

     4.匿名函数:

     什么是: 定义函数时,不写名的函数

      何时: 如果一个函数只用一次,不会反复使用,就不起函数名

      为什么: 节约内存!——使用一次后,自动释放!

      如何:

       2种场景:

       a). 回调函数: 自己定义的函数,自己不调用,而是传给其它对象或函数,被别人调用。

         arr.sort(function(a,b){return a-b})

         xhr.onreadystatechange=function(){ ... }

         pool.query(sql,[参数],function(err,result){ ... })

       b). 匿名函数自调: 定义函数后,立刻自己调用自己

         为什么: 避免使用全局变量,造成全局污染

         何时: 所有js代码都应该封装在一个匿名函数自调中

         如何:

          (function(){

            ...

          })()//调用后,匿名函数内的局部变量都释放了

     

    5. Function作用域和作用域链

     

     

    6.闭包

    闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁

     

     

     

     

    四. OOP

     1.什么是对象:

    程序中,描述现实中一个具体事物的程序结构

     为什么: 便于维护

     2.什么是面向对象:

    程序中,都是先将多个事物的属性和功能,封装为多个对象,再按需调用对象的成员

     何时: 今后,几乎所有程序,都用面向对象方式实现的

     如何使用: 封装,继承,多态——三大特点

     3.面向对象三大特点:

      封装:创建一个对象,集中保存一个具体事物的属性和功能

       为什么: 便于大量数据维护

       何时: 只要使用面向对象编程,都要先封装对象,再按需使用对象的成员

      如何: 3种:

        1). 用{}:

         var obj={

           属性名: 值,

             ... : ... ,

           方法: function(){ ... this.属性名... },

             ... : ...

         }

     访问对象的成员: =属性+方法

          属性其实就是保存在对象中的变量

            对象.属性

          方法其实就是保存在对象中的函数

            对象.方法()

         this: 

          什么是: 在函数调用时,自动指向 . 前的对象的关键词

          为什么用: 避免在对象的方法中写死对象名,形成紧耦合。

          何时用: 只要对象自己的方法,想访问自己的成员时,都要加this.

          强调: 笔试时:

           a). this和定义在哪儿无关,只和调用时.前的对象有关

           b). 全局函数调用没有 . , this默认指window

     

        2). 用new创建: 2步:

         var obj=new Object();

         obj.属性名=值;

              ... = ...;

         obj.方法名=function(){ ... this.属性名 ...}

         揭示: js中一切对象底层,都是关联数组

          *). 访问不存在的成员,不报错,返回undefined

          *). 强行给不存在的成员赋值,不报错,而是强行赋值新成员

          *). 同样可用for in循环遍历一个对象中的所有成员

          *). 访问下标: 2种:

             1. obj["下标"] 如果属性名需要动态获得

             2. obj.下标 如果属性名是写死的

    问题: 一次只能创建一个对象,如果反复创建多个相同结构的对象时,代码会很冗余

        解决: 用构造函数创建对象:

        3). 用构造函数反复创建多个相同结构的对象:

         什么是构造函数: 描述同一类型所有对象的统一结构的函数

         何时: 反复创建多个相同结构的对象

         如何:

          定义构造函数:

           function 类型名(形参1,形参2,...){

             this.属性名=形参1;

             this. ... =形参2;

             this.方法名=function(){ ... this.属性名 ...}

           }

          反复调用构造函数,创建多个相同类型的对象

           var lilei=new 类型名(实参,...);

           new 4件事:

            *). 创建一个新的空对象: {}

            *). 让新对象自动继承构造函数的原型对象: 新对象._ _proto_ _=构造函数.prototype 

            *). 用新对象调用构造函数:

                自动将构造函数中的this->new

                通过强行赋值新属性的方式,自动添加规定的属性到新对象中,并将参数值,保存到新对象的对应属性中

            *). 返回新对象的地址给变量

        构造函数优点: 重用结构

        缺点: 无法节约内存!

      继承:

       什么是: 父对象的成员,子对象无需重复创建就可直接使用

       为什么: 重用代码,节约内存

       何时: 只要在多个子对象中包含部分相同的成员时

       如何:

        /****** 必须知道的原理 *******/

        js中的继承都是继承原型对象(prototype)

         什么是原型对象: 集中保存所有子对象共有成员的父对象

         创建原型对象: 买一赠一

           每创建一个构造函数,就附赠一个空的原型对象

             构造函数.prototype

         何时继承:

           new的第2步: 让新对象自动继承构造函数的原型对象: 新对象._ _proto_ _=构造函数.prototype

     继承里的自有属性和共有属性:

       自有属性: 保存在当前对象本地,仅归当前对象自有的属性

       共有属性: 保存在原型对象中,归多个子对象共有的属性

       取值/访问时: 对象.成员名

       修改时: 修改自有属性: 子对象.属性=值

               修改共有属性: 原型对象.共有属性=值

         如果强行用子对象.共有属性=值

          后果: 为子对象自己添加一个同名的自有属性,从此子对象与父对象再无关系。——错误!

    内置对象的原型对象:

       内置对象: ES标准中规定的,浏览器已经实现了的,咱们可以直接使用的对象

       js内置对象: 11个:

        String  Number  Boolean  Array  Date  RegExp  Math  Error  Function Object  global

    其实,每种内置对象(除Math和global外)都是一种类型:

        都由两部分组成:

        1. 构造函数: 创建该类型的子对象

        2. 原型对象: 保存该类型共有的函数

     原型链:

       什么是: 多级原型对象逐级引用形成的链式结构

       作用: *. 保存了一个对象可用的所有成员

            *. 控制着成员的使用顺序: 先自有,再共有

     

     多态:

      什么是: 一个函数在不同情况下表现出不同的状态

      2种:

      *. 重载:

      *. 重写(override): 子对象中定义了和父对象中同名的成员

       何时: 只要子对象觉得父对象的成员不好用,就要定义自有的,来屏蔽父对象的。

     

    4.自定义继承

     

     

     

     

     

     

     

     

     

                                                            

     

    5.静态

    静态(static)方法:

     先了解什么是实例(instance)方法: 必须先有一个实例对象,才能调用的方法

        比如: var arr=[1,2,3];   arr.sort()

             var str="Hello";   str.toUpperCase()

        限制: 只有当前类型的子对象,才能使用的方法

      什么是静态方法: 不需要任何实例,就可用类型名直接调用的方法(不是用具体的对象object调而是用·前的类型名)

        比如: Object.setPrototypeOf()

        何时使用: 2种:

          1. 不确定使用该方法的对象的类型时

          2. 调用函数时,暂时无法确定要使用该函数的对象是什么

        如何定义:

         定义实例方法: 将方法添加到原型对象中

         定义静态方法: 将方法添加到构造函数对象上

                          构造函数.静态方法=function(){ ... }

     

    五. ES5:

    1. 严格模式:

      什么是: 比普通js运行要求更严格的模式

      为什么: js语言本身有很多广受诟病的缺陷

      何时: 今后所有js代码都要运行在严格模式下

      如何: 在当前作用域的顶部: "use strict";

     

      要求:

       *). 禁止给未声明的变量赋值:

       *). 静默失败升级为错误:

        静默失败: 执行不成功,也不报错!

     

       2). 禁用了arguments.callee

        arguments.callee: 在调用函数时,自动获得当前正在执行的函数本身(其实是ES5禁用递归)。

         何时: 专门用于在递归算法中,代替写死的函数名

        递归的问题: 效率极低!是因为重复计算量太大!

        解决: 几乎所有的递归都可以用循环代替

       3). 普通函数调用和匿名函数自调中的this不再指向window,而是undefinde

    2.保护对象:

      为什么: js中的对象毫无自我保护能力

      何时: 如果不希望别人擅自修改对象的属性和结构时

      1).如何:

       保护属性:

        将所有属性划分为2大类:

         命名属性: 可用 . 访问到的属性

          又分为2类:

           数据属性: 直接存储属性值的属性

           访问器属性: 不实际存储属性值,仅负责提供对另一个数据属性的保护。

         内部属性: 不能用 . 访问到的属性

        数据属性:

         ES5规定,每个数据属性,其实是一个缩微的小对象

         每个属性对象其实包含四个特性: {

          value: 实际存储属性值,

          writable: 控制是否可修改,

          enumerable: 控制是否可被for in遍历,但用.依然可以访问

          configurable: 控制是否可删除该属性

                      控制是否可修改其它两个特性

          默认: 三个开关都是true

          获取一个属性的四大特性:

          var attrs=Object.getOwnPropertyDescriptor(obj,"属性名")

            获得obj对象的指定"属性"的四大特性

         打开和关闭开关:

          Object.defineProperty(obj,"属性名",{

          重新定义obj的指定"属性"的开关

            开关: true/false,

             ... : ...

          })

          问题: 一次只能修改一个属性的四大特性

          解决:

          Object.defineProperties(obj,{

            属性:{

              开关:true/false,

               ... : ...

            },

            属性:{

             ... ...

            }

          })

          问题: 无法使用自定义规则保护属性

          解决:

        访问器属性:

         何时: 只要使用自定义规则保护一个数据属性时

         如何:

          前提: 必须先有一个隐藏的数据属性,实际存储属性值

          定义访问器属性:

          使用访问器属性:

     

    完善以上俩个构造函数的综合 

      

    2).保护结构: 禁止添加/删除对象中的属性

        3个级别:

        *). 防扩展: 禁止添加新属性

          Object.preventExtensions(obj)

           禁止给obj对象添加任何新属性

    再试图添加,就会出现错误

           原理: 每个对象中都有一个内部属性: extensible:true

            preventExtensions()将对象的extensible:false

        *). 密封: 在兼具防扩展同时,再禁止删除现有属性

          Object.seal(obj)

           禁止向obj中添加新属性

           禁止删除obj中现有属性

           原理: 将extensible:false

                同时还将每个属性的configurable:false

        *). 冻结: 在兼具密封的基础上,同时禁止修改所有属性值

           Object.freeze(obj)

           禁止向obj中添加新属性

           禁止删除obj中现有属性

           禁止修改任何属性的值

           原理: 自动将每个属性的writable改为false

    一般用于冻结公共属性

     

    3.call/apply/bind()

    替换this:

      1). 临时调用一次函数,并临时替换一次this:

        call: 传入函数的每个实参必须作为一个单独的参数传入

        apply: 传入函数的每个实参必须放在一个数组中整体传入(apply的比call多一个功能就是打散数组,但结果和call是一样的)

          何时: 如果所有实参是放在一个数组中给你的

      2). 不调用函数,而是创建一个原函数的副本,副本永久绑定this和部分参数值: bind

          何时使用: 修改回调函数的this时只能用bind

     

     4.数组API:

      1). 查找: indexOf: 同String中的indexOf

         何时使用: 在数组中查找一个指定元素的位置时

     

      2). 判断:

         判断数组中的元素是否符合要求

         *). 判断数组中的元素是否都符合要求

          var bool=arr.every(function(elem, i, arr){

            return 判断结果

          })

          every会自动拿着回调函数在每个元素上执行一次:

            参数: elem自动得到当前元素值

                   i 自动得到当前位置

                   arr 自动得到当前数组对象

            返回值: 利用获得的参数,判断当前元素是否符合要求,并返回判断结果。

            只有回调函数在每个元素上执行都返回true时,才整体返回true。只要碰到一个false,就返回false

         *). 判断数组中是否包含符合要求的元素

          var bool=arr.some(function(elem, i, arr){

            return 判断条件

          })

    some和every不同的地方是只要包含一个满足条件的整个some就返回true

      3). 遍历API: 对数组中每个元素执行相同的操作

       *). 遍历原数组中每个元素,执行相同的操作:

        arr.forEach(function(elem, i, arr){

          对原数组中的元素值,执行操作

        })

       *). 依次取出原数组中每个元素,执行相同的操作后,放入新数组中返回:

        var newArr=arr.map(function(elem,i,arr){

          return 新值

        })

     

      4). 过滤和汇总:

       过滤: 复制出数组中符合条件的元素,组成新数组返回

        var subArr=arr.filter(function(elem,i,arr){

          return 判断条件

        })

       汇总: 对数组中每个元素的值进行统计,得出一个汇总的结果。

        var result=arr.reduce(

              function(prev,elem,i,arr){

            //prev: 获得截止目前的临时汇总值

            return prev+elem

          },

          base//起始时的基数

        )

     

    六.ES6:

    ES6:不改变原理的基础上,让API变的更简化

    1. let: 代替var用于声明变量

     1). var的缺点:

       *). 声明提前:

       *). 没有块级作用域:

      2).let的优点:

       *). 阻止了声明提前

       *). 让let所在的块({...})也变为一级作用域

     

    2.参数增强:

      1). 默认值: ES6中可以给形参提前设置一个默认值,调用时,如果没有给实参,就自动启用默认值代替。

        如何: function fun(形参1, 形参2,..., 形参n=默认值){}

        强调: 带默认值的形参必须出现在参数列表的末尾

      2). 剩余参数:

        代替arguments:

         arguments的问题:

          *). 不是纯正的数组类型,而是类数组对象,导致数组的所有API,arguments不能使用

          *). 只能接住所有参数,不能有选择的接住部分参数

        如何使用剩余参数:

         function fun(形参1, 形参2,...数组名){

           //数组中就接住了除形参1,形参2以外的剩余的实参

           //且"数组"是纯正的数组类型,可以使用所有数组家的API

         }

    *注意:...三个点是语法,作用是收集

        剩余参数的优点:

         *). 是纯正的数组,可使用所有数组家API
          *). 可有选择的获得剩余参数

     3). 散播(spread):

       代替apply,用于专门打散数组类型参数为单个值

        apply的问题: 其实apply的主要功能是替换this,顺便打散数组类型参数

       何时: 只要单纯希望打散数组类型参数为单个值时

       如何:

        调用时: fun(...数组名)

               先把数组打散后,再分别传给fun

               相当于: fun(数组[0],数组[1],数组[2],...)

    *注意:...三个点是语法,作用是打散

    3. 箭头函数: 简写一切匿名函数

    1).简化

      *). 去function变=>

      *). 如果只有一个参数,可省略()

      *). 如果函数体只有一句话,可省略{}

          如果仅有的一句话是return... ,则必须省略return

     

      特性: 内外this通用!

       如果和this无关时,或希望内外this通用时,可改箭头函数

       如果不希望内外this通用时,就不能用箭头函数

    4.解构: 提取出一个大的对象中的部分成员,单独使用。

      1). 数组解构: 下标对下标:

       var arr=[elem1, elem2,...];

                           ||    ||

               var [变量1,变量2,...]=arr;

       变量1=elem1

       变量2=elem2

      2). 对象解构: 属性对属性

       var obj={属性1:值1,    属性2:值2,  ... }

                     ||            ||

          var {属性1: 变量1, 属性2:变量2, ... }=obj

        变量1=值1;

        变量2=值2;

     

      3). 参数解构: 其实是对象解构在函数传参时的应用

        何时用: 多个形参都不确定是否有值时

        如何: *). 定义函数时: 将所有形参都定义在对象结构中

         function fun({

                     url:url,

            type:type,

            data:data,

            dataType:dataType

         }){

         }

         可简写为: function fun({url, type, data, dataType}){

        *). 调用时: 所有实参都要放在一个对象结构中整体传入

         fun({

           url:"http://localhost:3000/index",

           type:"get",

           //data:,

           dataType:"json"

         })

        结果:

           形参url ="http://localhost:3000/index

           形参type="get"

           形参data=undefined

           形参dataType="json"

     

     

         优点:

          *). 与参数个数无关

          *). 与参数顺序无关

     5.for of: 遍历索引数组

      1). for:

        for(var i=0;i<arr.length;i++){

          arr[i] //当前元素

        }

      2). forEach:

        arr.forEach( (elem,i,arr)=>{ elem //当前元素值 })

        不灵活:

         *). 不能控制顺序

         *). 不能控制步调

      3). for of

        for(var elem of arr){

          elem //当前元素值

        }

        不灵活: 只能获得元素值,不能获得元素位置

        vs for in:

         for of: 可遍历数字下标的索引数组或类数组对象

         for in: 只能遍历非数字下标的关联数组或对象(for in 不建议遍历索引数组,有风险,因为in不止遍历下标包括非数字的下标全部遍历,对于混搭的数组来说有风险)

     6.class: 对整个面向对象的简化:

      1).简化

      *). 对单个对象直接量的简化:

        var obj={

          属性1: 值1,

          属性2 : 变量,

          //如果属性名刚好和变量名相同,则只写一个

          方法名:function(){//所有方法,不再需要:function

            ... ...

          }

        }

      *). 对一种类型定义的简化: class

       *). 用class{}包裹构造函数和原型对象方法

       *). 将构造函数名提升为类型名,构造函数统一更名为constructor

       *). 所有原型对象方法不用再添加到Prototype中,而是直接写在class内,与构造函数平级(不要逗号)

       class Plane {

         constructor (fname,speed,score){

           this.fname=fname;

           this.speed=speed;

           this.score=score;

         }

         fly(){ ... }

         getScore(){ ... }

       }

     

      2). 继承:

        *). 让子类型继承父类型:

          class Child extends Father{

          extends代替了Object.setPrototypeOf(...)

        *). 子类型构造函数中必须先借用父类型构造函数:

          class Child extends Father{

            constructor(...){

              super(参数,...)//借父类型的构造函数

              this.xxx=xxx;

            }

          }

          super代替了Father.call(this,...)

          super中不要加this!

      3).封装

       *).访问器属性:

       class 类名{

         constructor(..., age){

           ... ...

           半隐藏的_age属性

           this.age=age;

         }

         get age(){ return this._age;}

         set age(value){验证value并赋值}

       }

     

      *). 静态方法:

       class 类名{

        constructor(){

        }

            //必须使用当前类型的子对象才能调用的方法,称为实例方法。

        实例方法(){ ... }

        //不需要使用当前类型的子对象,就可用类型名直接调用的方法

        static 静态方法(){ ... }

       }

       调用时:

       //静态方法不需要提前创建任何该类型的子对象,就可用类型名直接调用

       类型名.静态方法()

       var obj=new 类型名()

       //实例方法要求必须先创建该类型的子对象,才可用子对象调用实例方法。

       obj.实例方法()

     

    7.promise

    1).何时:多个异步方法,要求必须顺序执行时。

    2).为什么:为了解决回调地狱问题

    回调地狱:因为回调函数的嵌套层级太深导致的代码可读性差。

    造成根源:异步函数的下一项任务,只能在函数调用初期就提前传入函数

    3). 如何实现promise

     需要修改的几个地方

     Object.create()

      什么是: 创建一个新对象,让新对象继承指定的父对象

      何时: 在没有构造函数的情况下,也想创建子对象继承父对象时

      如何:

        var child=Object.create(father,{

           自有属性:{

             value:值,

             三个开关...

           }

        })

  • 相关阅读:
    JZOI 4020 Revolution
    JZOJ 4018 Magic
    JZOJ 4017 逃跑
    JZOJ 4016 圈地为王
    JZOJ 4015 数列
    JZOJ 3960 鸡腿の出行
    BZOJ 5005 & JZOI 3959 鸡腿の乒乓
    GCJ2009B&JZOJ 4033 Min Perimeter
    jzoj 3948 Hanoi 塔
    [纯符][纯粹的无聊] 神奇的递推式
  • 原文地址:https://www.cnblogs.com/liuqingqing-bloom/p/12389923.html
Copyright © 2020-2023  润新知