前端知识点总结——JS高级(持续更新中)

前端知识点总结——JS高级(持续更新中)

1.字符串

什么是: 连续存储多个字符的字符数组
相同: 1. 下标 2. .length 3. 遍历前端

4. 选取: slice(starti[, endi])

不一样: 类型不一样 API不通用
API: 全部字符串API都无权修改原字符串,老是返回新字符串正则表达式

  1. 大小写转换:
    统一转大写: str=str.toUpperCase()
    统一转小写: str=str.toLowerCase()
    什么时候: 不区分大小写时,都须要先转为一致的大小写,再比较。

说明: 验证码本不应客户端作,应该由服务器端完成数据库

2.获取指定位置的字符:

str.charAt(i) => str[i]
获取指定位置字符的unicode号
str.charCodeAt(i)小程序

将unicode号转为汉字: String.fromCharCode(unicode)

3.获取子字符串:

str.slice(starti,endi+1)
强调: 若是一个API,两个参数都是下标,则后一个参数+1(含头不含尾)
str.substring(starti,endi+1) 用法和slice彻底同样
强调: 不支持负数参数
str.subStr(starti,n) 从starti开始,取n个
强调: 第二个参数不是下标,因此,不用考虑含头不含尾数组

4.查找: 4种:

  1. 查找一个固定的关键词出现的位置:
    var i=str.indexOf("关键词"[,fromi])
    在str中,fromi位置后,找下一个"关键词"出现的位置
    若是找到,返回关键词第一个字的下标位置
    若是没找到,返回-1
    说明: fromi可省略,默认从0开始

    var i=str.lastIndexOf("关键词");
    在str中,查找"关键词"最后出现的位置promise

    问题: 只能查找一个固定的关键词
    卧我草/操/艹/槽
    微 信 w x wei xin
    解决: 用正则查找:浏览器

  2. 判断是否包含关键词:
    var i=str.search(/正则/)
    返回值: 若是找到,返回关键词的位置服务器

    若是没找到,返回-1

    问题: 默认,全部正则都区分大小写
    解决: 在第二个/后加i ignore 忽略
    问题: 只能得到位置,没法得到本次找到的敏感词的内容网络

  3. 得到关键词的内容:
    var arr=str.match(/正则/i);
    2种状况:闭包

    1. 不加g的状况: 只能返回第一个找到的关键词内容和位置: [ 0: "关键词内容", index: 位置 ]
    2. 加g: 返回全部找到的敏感词的内容,保存在数组中。g: global

强调: 若是找不到,返回null

警告: 凡是一个函数可能返回null!都要先判断不是null,才能用!

问题: 只能得到关键词内容,没法得到位置

  1. 即找每一个关键词内容,又找每一个关键词位置:
    reg.exec()

5.替换:

什么是: 将找到的关键词替换为指定的内容
如何: 2种:

  1. 简单替换: 将全部敏感词无差异的替换为统一的新值
    str=str.replace(/正则/,"替换值")
  2. 高级替换: 根据每一个敏感词的不一样,分别替换不一样的值
    str=str.replace(/正则/,function(kw){

    //kw: 会自动得到本次找到的一个关键词
     return  根据kw的不一样,动态生成不一样的替换值

    })

衍生: 删除关键词:
str=str.replace(/正则/,"")

6.正则表达式: Regular Expression

什么是: 描述一个字符串中字符出现规律的规则的表达式
什么时候: 2种:

  1. 查找关键词:
  2. 验证:

如何: 正则表达式语法:

  1. 最简单的正则实际上是关键词原文:

7.字符集:

什么是: 规定一位字符,备选字符列表的集合
什么时候: 只要一位字符,有多种备选字时
如何: [备选字符列表]
强调: 一个[]只能匹配一位字符
简写: 若是备选字符列表中部分字符连续

可简写为: [x-x]  用-省略中间字符
 好比: [0-9] 一位数字
      [a-z] 一位小写字符
      [A-Z] 一位大写字母
      [A-Za-z] 一位字符
      [0-9A-Za-z] 一位字母或数字
      [\u4e00-\u9fa5] 一位汉字

反选: 1 除了4和7都行

8.预约义字符集: 4种:

d 一位数字 [0-9]
w 一位数字,字母或下划线 [0-9A-Za-z_]
强调: 只有100%匹配时,才使用w,若是不容许有_,则使用自定义字符集
s 一位空字符,好比: 空格,Tab,...
. 通配符
问题: 字符集只能规定字符的内容,没法灵活规定字符的个数

9.量词:

什么是: 专门规定一个字符集出现次数的规则
什么时候: 只要规定字符集出现的次数,都用量词
如何: 字符集量词
强调: 量词默认只修饰相邻的前一个字符集
包括: 2大类:

1. 有明确数量边界:
 {6,8}  最少6次,最多8次
 {6,}   最少6次,多了不限
 {6}    必须6次,不能多也不能少
2. 没有明确数量边界:
 ?     无关紧要,最多1次
 *     无关紧要,多了不限
 +     至少1次,多了不限

10.选择和分组:

  1. 选择: 或
    规则1|规则2
    什么时候: 只要在两个规则中任选其一匹配
  2. 分组: (规则1规则2...)
    什么时候: 若是但愿一个量词同时修饰多个规则时,都要先将多个规则分为一组,再用量词修饰分组。

    好比: 车牌号: [\u4e00-\u9fa5][A-Z]•[0-9A-Z]{5}
    好比: 手机号规则: 
    \+86或0086  无关紧要,最多1次
    空字符      无关紧要,多了不限
     1
     在3,4,5,7,8中选一个

    9位数字
    (+86|0086)?s*1[34578]d{9}

    好比: 身份证号:

    15位数字 2位数字 一位数字或X

    无关紧要,最多一次
    \d{15}(\d{2}[0-9X])?
    好比: 电子邮件: 鄙视

    /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
    好比: url:
    (https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]

11.匹配特殊位置: 3个:

  1. 字符串开头: ^
  2. 字符串结尾: $
    好比: 开头的空字符: ^s+

    结尾的空字符: \s+$
     开头或结尾的空字符: ^\s+|\s+$

    3.单词边界: b 包括开头,结尾,空字符,标点符号

    好比: 单词首字母: \b[a-z]
    匹配单词: \bxxx\b

12.String:

替换: 2种: 若是关键词是固定的:
str=str.replace("关键词","替换值");
若是关键词变化
str=str.replace(/正则/ig,"替换值");
切割: 2种: 若是分隔符是固定的:
var substrs=str.split("分隔符")
若是分隔符不是固定的
var substrs=str.split(/正则/i)
固定套路: 将字符串打散为字符数组

var chars=str.split("")

13.RegExp:

什么是: 保存一条正则表达式,并提供用正则表达式执行验证和查找的API
什么时候: 只要用正则查找关键词或验证字符串格式时
如何:
建立: 2种:

  1. 直接量: var reg=/正则/ig
    什么时候: 只要正则表达式的规则是固定不变的。
    问题: 正则表达式时固定不变的,不支持动态生成
  2. new: var reg=new RegExp("正则","ig");
    什么时候: 只要须要动态生成正则表达式

API: 2个:

  1. 验证: var bool=reg.test(str)
    问题: 默认,只要找到匹配的内容,就返回true,不要求完整匹配!
    解决: 从此,凡是验证必须前加^,后加$
  2. 查找: 即找每一个关键词位置,又得到每一个关键词内容
    var arr=reg.exec(str)
    在str中查找下一个关键词的位置和内容
    返回值: arr:[ 0: 内容, index: 位置 ]
    若是找不到,返回null
    若是找全部: 只要用while反复调用reg.exec便可,exec可自动跳到下一个查找位置

14.Math

什么是: 保存数学计算的常量和API的对象
什么时候: 进行算术计算
如何:
建立: 不用建立,全部API都用Math直接调用
API:

    1. 取整:
      上取整: Math.ceil(num)
      下取整:
      Math.floor(num)
      parseInt(str) 去掉字符串结尾非数字字符(单位)
      四舍五入取整:
      Math.round(num)
      优: 返回数字类型,可直接计算
      缺: 不能随意指定小数位数
      n.toFixed(d)
      优: 可随意指定小数位数
      缺: 返回字符串类型,不能直接作加法
      自定义round
    1. 乘方和开平方:
      Math.pow(底数,幂)
      Math.sqrt(num)
    2. 最大值和最小值
      Math.max(值1, 值2,...)
      Math.min(值1, 值2,...)
      问题: 不支持数组
      解决: Math.max(...arr)
    3. 随机数:
      Math.random() 0~1 随机小数
      公式: 在min到max之间取一个随机整数
      parseInt(Math.random()*(max-min+1)+min)
      简写: 在0~max之间取一个随机整数
      parseInt(Math.random()*(max+1))
    4. 三角函数:
      已知角度,求边长,用三角函数: sin cos tan
      已知边长,求角度,用反三角函数: asin acos atan
      仅以atan:
      var 弧度=Math.atan(对边长/邻边长)

      360角度=2π弧度

      问题: atan没法区分角度的象限
      解决: Math.atan2(对边长, 邻边长);

    15.Date:

    什么是: 保存一个时间,提供操做时间的API
    什么时候: 只要在程序中存储时间或操做时间,都用date
    如何:
    建立: 4种:

    1. 建立日期对象,并自动得到客户端当前系统时间
      var now=new Date();
    2. 建立日期对象,保存自定义时间
      var now=new Date("yyyy/MM/dd hh:mm:ss");
    3. 用毫秒数建立日期对象:
      var date=new Date(ms)
    4. 复制一个日期对象:
      问题: 日期的计算都是直接修改原日期对象
      解决: 若是但愿同时保留计算先后的开始和结束时间,都要先复制开始时间,再用副本计算结束时间
      var date2=new Date(date1)

    本质: 起始日期对象内部保存的是一个巨大的毫秒数:

    1970年1月1日至今的毫秒数

    文字存储日期的问题:

    1. 有时区问题:
    2. 不便于计算:

    毫秒数存储日期:

    1. 不受时区的干扰: 
    2. 便于计算:

    总结: 未来在网络中传输或在数据库中存储时间,都用毫秒数

    16.API:

    1. 8个单位:
      FullYear Month Date Day
      Hours Minutes Seconds Milliseconds
    2. 每一个单位上都有一对儿get/set方法:
      getXXX() 负责得到单位的值
      setXXX() 负责修改单位的值
      特例: Day 不能修改,没有setDay()
    3. 取值范围:
      Month: 0~11 计算机中的月份老是比现实中小1
      Date: 1~31
      Day: 0~6
      Hours: 0~23
      Minutes/Seconds: 0~59

    日期计算:

    1. 两日期相减: 获得的是毫秒差
      什么时候: 计算时间段或计算倒计时
    2. 对任意单位作加减: 3步:

      1. 得到单位的当前值
      2. 作加减
      3. 将计算后的结果set回去
        setXXX()可自动调整时间进制

    可简化为: date.setXXX(date.getXXX()+n)
    问题: setXXX()直接修改原日期
    解决: 若是同时保存计算先后的开始和结束时间,应该先复制副本,再用副本计算。

    17.Date:

    日期格式化:
    date.toString() 默认当地时间的完整版格式
    date.toLocaleString() 转为当地时间的简化版格式
    date.toLocaleDateString() 仅保留日期部分
    date.toLocaleTimeString() 仅保留时间部分

    18.Error:

    什么是错误: 程序执行过程当中,遇到的没法继续执行的异常状况
    程序出错,都会强行中断退出。
    什么是错误处理: 即便程序出错!也保证不会中断退出
    什么时候: 若是但愿程序,即便出错,也不会强行中断退出
    如何:
    try{
    可能出错的正常代码
    }catch(err){
    //err: 错误对象, 自动保存了错误的信息
    只有出错才执行的错误处理代码:
    提示错误信息, 记录日志, 释放资源
    }
    问题: 效率略低
    解决: 多数try catch,都能用if...else代替

    主动抛出错误:
    throw new Error("错误信息")
    鄙视: js中共有几种错误类型: 6种:
    SyntaxError 语法错误
    ReferenceError 引用错误
    TypeError 类型错误
    RangeError 范围错误 参数超范围

    EvalError URIError

    19.Function:

    什么是函数: 保存一段代码段的对象,再起一个名字。
    为何: 代码重用
    什么时候: 只要一段代码可能被重复使用时!
    如何:
    建立: 3种:

    1. 声明: function 函数名(参数列表){

      函数体;
            return 返回值;
          }

      参数: 调用函数时,接收传入函数的数据的变量
      什么时候: 若是函数自身必须某些数据才能正常执行时,就必须定义参数,从外部接收必须的数据
      返回值: 函数的执行结果
      什么时候: 若是调用者须要得到函数的执行结果时
      调用: var 返回值=函数名(参数值列表);
      问题: 声明提早: 在程序开始执行前,先将var声明的变量和function声明的函数,提早到当前做用域的顶部集中建立。赋值留在原地。
      解决:

    2. 直接量: var 函数名=function (参数列表){
      特色: 不会被声明提早
      揭示: 函数名其实只是一个变量

      函数实际上是一个保存代码段的对象
        函数名经过对象地址引用函数对象
    3. new :
      var 函数名=
      new Function("参数1","参数2",...,"函数体")

    20.重载overload:

    什么是: 多个相同函数名,不一样参数列表的函数,在调用时,可根据传入的参数不一样,自动执行不一样的操做。
    为何: 为了减小API的数量,减轻调用者的负担
    什么时候: 只要一项任务,可能根据传入参数的不一样,执行不一样的流程时。
    如何: js语法默认不支持重载!

    由于: js中不容许多个同名函数,同时存在。最后一个函数会覆盖以前的。
    变通实现: arguments
     什么是: 每一个函数中,自动包含的,接收全部传入函数的参数值的类数组对象
       类数组对象: 长得像数组的对象
         vs 数组: 相同: 1. 下标, 2. .length, 3. 遍历
                 不一样: 类型不一样, API不通用

    21.匿名函数:

    什么是: 定义函数时,不指定函数名
    为何: 节约内存 或 划分临时做用域
    什么时候:

    1. 只要一个函数,但愿调用后,马上自动释放!
    2. 划分临时做用域:

    如何:

    1. 回调: 定义函数后,本身不调用,而是传递给另外一个函数去调用
    2. 自调: 定义函数后,马上调用本身。
      什么时候: 从此全部js代码必须都放在匿名函数自调中,避免全局污染。

    22.垃圾回收:

    什么是垃圾: 一个再也不被任何变量使用的对象
    什么是垃圾回收: js引擎会自动回收再也不被使用的对象的空间。
    为何: 内存空间都是有限的!
    垃圾回收器: 专门负责回收垃圾对象的小程序——js引擎自带
    如何:

    1. 程序执行时,垃圾回收器伴随主程序执行而执行。
    2. 每建立一个对象,垃圾回收器就会记录对象被几个变量引用着.
    3. 若是发现一个对象再也不被任何变量应用,则自动回收该对象的存储空间。

    好的习惯: 只要一个对象再也不使用,就要赋值为null

    23.做用域和做用域链

    做用域(scope): 一个变量的可用范围
    为何: 避免内部的变量影响外部
    本质: 是一个存储变量的对象
    包括: 2种:

    1. 全局做用域: window
      保存全局变量: 随处可用,可反复使用
    2. 函数做用域: ?
      保存局部变量: 仅在函数内可用,且不可重用!

    24.函数生命周期:

    1. 程序开始执行前
      在内存中建立执行环境栈(数组): 用于保存正在调用的函数任务。
      在执行环境站中添加第一条记录: 调用浏览器主程序
      建立全局做用域对象window: 2个做用:

      1. 保存浏览器本身须要的数据和对象
      2. 做为程序的全局做用域对象,保存全局变量
    2. 定义函数时:
      在window中定义函数名变量
      建立函数对象保存函数定义
      函数名变量引用函数对象
      函数对象的scope属性,又指回了函数建立时的做用域
    3. 调用函数时
      在执行环境栈中添加了本次函数调用的记录
      建立本次函数调用的函数做用域对象AO
      在AO中添加函数的局部变量
      设置AO的parent指向函数的scope
      执行环境栈中的函数调用记录,引用AO
      变量的使用顺序: 先用局部,再用全局
    4. 函数调用后
      本次函数调用的记录从执行环境栈中出栈
      致使AO被释放, 致使全部局部变量都释放

    25.做用域链:

    什么是: 由多级做用域对象,逐级引用造成的链式结构
    2个做用:

    1. 保存全部变量
    2. 控制着变量的使用顺序!

    26.闭包closure:

    什么是: 即重用一个变量,又保护变量不被污染的一种机制
    为何: 全局变量和局部变量都具备不可兼得的优缺点:
    全局变量: 优: 可重用, 缺: 易被污染
    局部变量: 优: 仅函数内可用,不会被污染

    缺: 不可重用!

    什么时候: 只要一个变量,可能被重用,又不想被篡改
    如何: 3步:

    1. 用外层函数包裹要保护的变量和内层函数
    2. 外层函数将内层函数返回到外部
    3. 调用外层函数,得到内层函数的对象,保存在外部的变量中——造成了闭包

    闭包造成的缘由: 外层函数调用后,外层函数的函数做用域对象没法释放
    主动使用闭包: 为一个函数绑定一个专属的变量
    鄙视: 画简图

    1. 找受保护的变量,并肯定其最终值
    2. 找内层函数对象
      外层函数向外返回内层函数对象: 3种:

      1. return function(){}
      2. 全局变量=function(){}
      3. return arr/obj{function(){...}}

    27.OOP

    什么是对象: 内存中存储多个数据的独立存储空间都称为一个对象。
    什么是面向对象: 程序中都是用对象结构来描述现实中一个具体事物。
    为何: 为了便于大量数据的维护和查找
    什么时候: 几乎全部js程序,都使用面向对象的方式开发
    如何: 三大特色: 封装,继承,多态
    封装: 用对象来集中描述现实中一个具体事物的属性和功能
    为何: 便于维护和查找
    什么时候: 从此只要使用面向对象的方式开发,都要先封装对象,再按需使用对象的属性和功能。
    如何: 3种:

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

      ... : ... ,

      //方法名:function(){...},
      方法名 (){...},
      }
      其中: 事物的属性值会成为对象的属性

      对象的属性本质是保存在对象中的一个变量
       事物的功能会成为对象的方法!
          方法的本质是保存在对象中的一个函数

      如何访问对象的成员:
      访问对象的属性: 对象.属性名
      调用对象的方法: 对象.方法名()
      问题: 对象本身的方法中要使用对象本身的属性
      错误: 直接用属性名,报错: 找不到变量

      为何: 默认,不加.就使用的变量,只能在做用域链中查找,没法自动进入对象中

      解决一: 对象名.属性名

      问题: 对象名仅是一个普通的变量名,可能发生变化。

      正确解决: this.属性名
      this: 自动指正在调用当前方法的.前的对象

      为何: 不受对象名变量的影响
      什么时候: 只要对象本身的方法向访问对象本身的属性时,都必须加this.

    js中对象的本质,其实就是一个关联数组

    1. 用new:
      var obj=new Object(); //建立空对象 等效于{}
      obj.属性名=值;
      obj.方法名=function(){
      ... this.属性名 ...
      }

    和关联数组同样,js中的对象也可随时添加新属性和方法。
    问题: 反复建立多个相同结构的对象时,重复代码太多,致使不便于维护
    解决:

    1. 用构造函数:
      构造函数: 描述一类对象统一结构的函数
      为何: 为了重用结构代码!
      什么时候: 只要反复建立相同结构的多个对象时,都用构造函数
      如何: 2步:

      1. 定义构造函数
        function 类型名(属性参数列表){
        this.属性名=属性参数;
        this. ... = 属性参数;
        this.方法名=function(){

        this.xxx

        }
        }

      2. 调用构造函数建立新对象
        var obj=new 类型名(属性值列表)
        new: 1. 建立新的空对象

        2. 设置新对象继承构造函数的原型对象
         3. 用新对象调用构造函数
           将构造函数中的this都指向新对象
         4. 返回新对象的地址

    问题: 构造函数只能重用代码,没法节约内存!
    解决: 继承:

    28.继承:

    什么是: 父对象的成员,子对象无需建立,就可直接使用
    为何: 代码重用,节约内存
    什么时候: 只要多个子对象,拥有相同的成员时,都应只在父对象中定义一份,全部子对象共用便可!
    如何: js中继承都是经过原型对象实现的

    什么是原型对象: 集中存储同一类型的全部子对象,共用成员的父对象
    什么时候: 只要继承,必然原型对象
    如何: 
     建立: 不用建立,买一赠一
       每建立一个构造函数,都附赠一个原型对象 
     继承: 在建立子对象时,new的第2步自动设置子对象继承构造函数的原型对象
     访问成员: 优先访问自有成员
              本身没有,就去父对象(原型对象)中查找
     将成员添加到原型对象中: 
      构造函数.prototype.成员=值

    自有属性和共有属性:
    自有属性: 保存在当前对象本地,仅归当前对象独有的属性
    共有属性: 保存在父对象中,全部子对象共有的属性
    读取属性值: 子对象.属性
    修改属性值: 自有属性,必须经过子对象本身修改

    共有属性,只能用原型对象修改!

    内置对象的原型对象:
    鄙视: 内置对象: 11个:

    String Number Boolean ——包装类型对象
    Array Date RegExp Math
    Error
    Function  Object
    Global (在浏览器中,被window代替)

    鄙视: 包装类型的理解

    什么是: 保存一个原始类型的值,并提供操做原始类型值的API
    为何: 原始类型的值自己不具备任何功能
    什么时候: 只要试图对原始类型的值调用API时,都会自动使用包装类型对象来帮助原始类型的值执行操做。
    如何: 
     1. 内存中已经预置了三大包装类型的对象:
       String  Number  Boolean
     2. 在试图对原始类型的值调用API时,自动检测原始类型的值的类型名
       var n=345.678;
         typeof n => number
     3. 根据类型名实例化对应的包装类型对象,调用其API
       new Number(n).toFixed(2) => 345.68
     4. 执行后,包装类型对象自动释放
       new Number释放!

    29.OOP

    面向对象三大特色: 封装,继承,多态
    继承:
    原型对象:
    内置类型的原型对象:
    一种类型: 包含两部分:

    1. 构造函数: 建立该类型的子对象
    2. 原型对象: 保存全部子对象的共有成员

    解决浏览器兼容性问题: 旧浏览器没法使用新API

    1. 判断当前浏览器对应类型的原型对象中是否包含该API
    2. 若是不包含,则自定义该API,添加到对应类型的原型对象中

    30.原型链:

    什么是: 由多级父对象,逐级继承造成的链式结构
    保存着: 全部对象的属性
    控制着: 对象属性的使用顺序:

    先自有,再共有

    鄙视: 如何判断一个对象是数组类型? 有几种方法
    错误: typeof : 只能区分原始类型,函数,没法进一步区分引用类型对象的具体类型名
    正确: 4种:

    1. 判断原型对象:
      obj.__proto__==Array.prototype
      Array.prototype.isPrototypeOf(obj)
    2. 判断构造函数:
      obj.constructor==Array
      obj instanceof Array

    问题: 不严格, 不但检查直接父对象,且检查整个原型链

    1. 判断对象内部的class属性

    class属性: 对象内部的专门记录对象建立时的类型名的属性
    问题1: class属性是内部属性,没法用.直接访问
    解决: 惟一的办法: Object.prototype.toString()
    问题2: 每种类型的原型对象都重写了各自不一样的toString()方法,子对象没法调用到Object.prototype.toString()
    解决: fun.call(obj) 让obj强行调用任何一个fun

    Object.prototype.toString.call(obj)
      在执行的一瞬间: obj.toString()
      结果:"[object Class]"

    鄙视: 什么时候将方法定义在原型对象中,什么时候将方法定义在构造函数上
    实例方法和静态方法:
    实例方法: 必须该类型的子对象才能调用的方法
    好比: arr.sort() arr.push()
    什么时候: 只要要求必须该类型的子对象才能调用
    如何: 全部放在原型对象中的方法都是实例方法
    静态方法: 不须要建立该类型的子对象,任何对象均可使用的方法。
    好比: Array.isArray(fun)

    Array.isArray(date)
        Array.isArray(obj)

    什么时候: 不肯定未来调用该函数的对象类型时
    如何: 添加到构造函数对象上的方法都是静态方法。可经过构造函数.静态方法方式直接调用!

    31.多态:

    什么是: 一个方法在不一样状况下表现出不一样的状态
    包括:

    1. 重载overload:
    2. 重写override:
      什么是: 若是子对象以为从父对象继承来的成员很差用,可在本地定义同名的自有成员,覆盖父对象的成员
      为何: 以为从父对象继承来的成员很差用
      什么时候: 只要以为从父对象继承来的成员很差用
      如何: 在本地定义同名的自有成员

    32.自定义继承:

    1. 只修改一个对象的父对象
      obj.__proto__=father
      Object.setPrototypeOf(obj,father)
    2. 修改全部子对象的父对象:
      构造函数.prototype=father
      时机: 在建立子对象以前换!
    3. 两种类型间的继承:
      什么时候: 发现多个类型之间拥有部分相同的属性结构和方法定义时,都要抽象父类型出来
      如何: 2步:

      1. 定义抽象父类型: 2步:

        1. 定义构造函数保存公共的属性结构
        2. 定义原型对象保存公共的方法
      2. 让子类型继承父类型: 2步:

        1. 在子类型构造函数中借用父类型构造函数
          错误: 直接调用: Flyer(fname,speed)
          缘由: Flyer不用.不用new调用,其中的this默认指window,Flyer中全部属性泄露到全局
          正确: 用call将正确的this注入到Flyer中,代替错误的this
          如何: Flyer.call(正确的this, fname,speed)
        2. 让子类型原型对象继承父类型原型对象
          Object.setPrototypeOf(子类型原型,父类型原型)

    33.ECMAScript6

    1. 严格模式:
      什么是: 比普通js运行机制要求更严格的模式
      为何: 普通的js运行机制有不少广受诟病的缺陷
      什么时候: 从此全部项目必须运行在严格模式下

      1. 若是新项目,整个js文件启用严格模式
      2. 旧项目,逐个函数启用严格模式

    如何:

    1. 在script或整个js文件顶部,添加"use strict";
    2. 在函数内顶部,添加"use strict";

    规则: 4个:

    1. 禁止给未声明的变量赋值
    2. 将静默失败升级为错误
    3. 普通函数或匿名函数自调中的this默认再也不指向window,而是undefined
    4. 禁止使用arguments, arguments.callee,...

    补: arguments.callee 自动得到当前正在调用的函数自己
    禁用,说明强烈不推荐使用递归!

    34.保护对象:

    保护对象的属性:
    ES5将对象属性分为:
    命名属性: 可用.直接访问到的属性
    数据属性: 直接存储属性值的属性
    保护数据属性: 4大特性:

    一个属性包含四大特性:{
      value: 实际保存属性值,
      writable: true/false, //只读
      enumerable: true/false, //不可遍历
        //不是完全隐藏,用.依然可访问!
      configurable:true/false //1. 禁止删除
                         //2. 禁止修改其它特性
                         //一旦改成false,不可逆
    }
    获取一个属性的四大特性:
    var attrs=Object.getOwnPropertyDescriptor(obj,"属性")
    修改四大特性:
    Object.defineProperty(obj,"属性",{
      四大特性:值
    })
    简写: Object.defineProperties(obj,{
           属性名:{
             特性:值,
             特性:值,
           },
           属性名:{
             ... : ...
           }
         })

    访问器属性: 不直接存储属性值,仅提供对另外一个数据属性的保护
    什么时候: 只要对一个属性提供自定义规则的保护
    如何:

    添加: 只能用Object.defineProperty和defineProperties添加
    四大特性: {
      get(){ return this.数据属性 }
      set(val){ 
        若是验证val经过
          this.数据属性=val
        不然
          报错
      }
      enumerable:
      configurable:
    }

    如何使用: 同普通的数据属性用法同样!

    在取值时,自动调用访问器属性内部的get
     在赋值时,自动调用访问器属性内部的set方法,同时将等号右边的新值,交给val参数

    问题: enumerable只能防住for in,防不住.,依然可用.直接修改被保护的数据属性
    解决:
    内部属性: 不能用.直接访问到的属性
    好比: class proto

    保护对象的结构: 3种

    1. 防扩展: 禁止给对象添加新属性
      Object.preventExtensions(obj)
      原理: 内部属性: extensible:true

      preventExtensions将extensible改成false
    2. 密封: 在防扩展同时,禁止删除现有属性
      Object.seal(obj)
      原理: 1. 将extensible改成false,禁止扩展

      2. 自动将全部属性的configurable都改成false
    3. 冻结: 在密封的同时,禁止修改一切属性值
      Object.freeze(obj)
      原理: 1. 兼具密封的全部功能

      2. 又将每一个属性的writable自动改成false!
    1. Object.create()
      仅用父对象,就可建立子对象,
      同时还可为子对象扩展自有属性
      var child=Object.create(father,{
      //Object.defineProperties
      属性名:{

      特性:值,
      特性:值,

      }
      })
      鄙视: 描述Object.create的执行原理

      1. 建立空对象child
      2. 自动设置child的__proto__为father
      3. 为child扩展新的自有属性

    35.call/apply/bind

    替换函数中不想要的this!
    call/apply: 马上调用函数,并临时替换中的this为指定对象
    什么时候: 只要调用函数时,函数中的this不是想要的就用call换成想要的
    若是传入函数的参数,是以数组形式,总体传入
    就用.apply(obj,arr)
    bind: 基于原函数,建立一个新函数,并永久绑定this为指定对象
    什么时候: 不会马上调用的函数(回调函数)中的this,不是想要的,就可用bind建立一个新函数,并永久绑定this!

    36.数组API:

    判断:

    1. 判断数组中全部元素是否都符合条件
      arr.every(function(elem,i,arr){

      //elem: 当前元素值
      //i: 当前位置 
      //arr: 当前数组对象
      return 判断条件

      })

    2. 判断数组中是否包含符合条件的元素
      arr.some(function(elem,i,arr){

      return 判断条件

      })

    遍历:

    1. forEach: 对原数组中每一个元素执行相同的操做
      arr.forEach(function(elem,i,arr){
      arr[i]=新值
      })
    2. map: 依次取出原数组中每一个元素执行相同操做后,放入新数组。原数组不变
      arr.map(function(elem,i,arr){
      return 新值
      })

    过滤和汇总:

    1. 过滤: 复制出原数组中符合条件的元素,放入新数组返回
      var subs=arr.filter(function(elem,i,arr){
      return 判断条件
      })
    2. 汇总: 将原数组中全部值统计出一个最终结论
      var result=arr.reduce(function(prev,elem,i,arr){
      //prev: 截止到目前,以前的临时汇总值
      return prev+elem;
      })

    37.let: 代替var

    为何
    问题1: 声明提早, 破坏程序原有执行顺序
    解决: let禁止在声明以前,提早使用该变量
    问题2: js没有块级做用域, 块内的变量,会污染到块外
    解决: let会将当前所在if/for/while...(){}变成块级做用域

    后果: 块内的let出的变量不会影响外部!

    原理: 其实let就是匿名函数自调!
    let与for循环,可造成闭包的效果
    强调: 原来块内外均可使用的变量,出了块,就不能用了!

    38.参数加强:

    默认值: function fun(参数1, 参数2,...,参数n=默认值)
    强调: 带默认值的参数必须定义在列表末尾
    原理: 参数n=参数n||默认值;
    rest: 代替了arguments
    什么时候: 当函数,不肯定参数个数时——重载
    为何: arguments的缺点:

    1. 类数组对象,不是数组
    2. 只能后去所有,不能有选择的分段获取

    如何: 定义函数时: function fun(参数1,参数2,..., ...数组名)
    数组名, 是一个纯正的数组,且可有选择的分段获取
    原理: var arr=[].slice.call(arguments[,starti]);//将类数组对象转为数组
    spread: 代替apply
    为何: apply虽然可打散数组类型参数为单个值,可是必须和替换this的操做捆绑使用
    什么时候: 只要仅须要打散数组类型参数为单个值时
    如何: 调用时: fun(参数值1,参数值2,...数组)

    1. 箭头函数: 代替回调函数中的function

    什么时候: 只要回调函数,都再也不使用function,而是使用箭头函数
    如何:

    1. 去function改=>
    2. 若是只有一个参数,可省略()
    3. 若是函数体只有一句话,则{}可省略

      更简化: 若是仅有的一句话仍是return,可省略return

    特色: 内外共用同一个this ——代替bind
    问题: 若是反而但愿内外this不通用时,就不能用箭头函数

    40.模板字符串: 代替+号拼接字符串

    ESLint规定,不容许使用+拼接字符串
    如何:

    1. 定义模板: 左右模板内容都必须放在``中
    2. 在模板中嵌入变量或表达式,动态生成内容:
      模板内,可用${...}嵌入任何合法的js变量或语句

    41.解构: 简化批量赋值

    什么是: 将一个对象/数组中的成员和元素,分别提取出来,单独使用。
    为何: 避免反复使用对象名/数组名
    什么时候: 只要但愿将一个大的对象或数组中的每一个成员单独取出使用时
    如何: 3种:

    1. 数组解构: 下标对下标
    2. 对象解构: 属性对属性
    3. 参数解构: 属性对属性
      定义函数时:
      问题: 普通函数的参数列表的顺序和个数是固定的
      解决: 使用对象语法定义参数列表
      优势: 未来传入的参数个数,顺序与对象列表无关
      调用函数: 也用对象语法传入参数
      赋值过程当中,采用对象结构的方式,为参数变量赋值

    42.for...of 在特定状况下,代替for循环

    什么是: 依次遍历数组/类数组对象中每一个元素的值
    vs for...in: 依次遍历关联数组/对象中每一个成员的属性名
    什么时候: 若是但愿从头至尾遍历整个数组或类数组对象
    如何:

    for(var elem of arr){
            elem
          }

    局限: 没法得到当前位置; 没法控制遍历的进度/顺序; 没法有选择的遍历部分

    43.class: 代替传统的封装,继承,多态的语法

    封装:

    class Student {
          constructor(sname,sage){
            ... ...
          }
          intr (){//Student.prototype.intr
            
          } 
          fun (){
        
          }
      }

    继承:

    class Flyer {
        constructor(fname,speed){
          ... ...
        }
        fly (){
          ... ...
        }
      }
      class Plane extends Flyer{
        constructor(fname,speed,score){
          //super指向父类型构造函数,且自动替换this
          super(fname,speed)
          ... ...
        }
        getScore (){
          ... ...
        }
     }

    静态方法:

    class User{
        constructor(uname,upwd){
          this.uname=uname;
          this.upwd=upwd;
        }
        save(){//保存在User.prototype中的实例方法
          console.log("保存当前对象");
        }
        static  findOne(){//静态方法,定义在构造函数上
          return new User();
        }
      }
      var user=new User(...);
      user.save();//调用实例方法
      User.findOne();//调用静态方法

    44.Promise: 解决: 回调地狱

    什么是callback hell: 因为使用参数传递回调函数,致使步骤多时,参数的嵌套层级很深。
    什么时候: 只要异步调用,可能发生延迟时,都要用Promise代替传统参数callback
    如何: 定义时

    function 第一件事(){
        return new Promise(fn=>{
          第一件事的内容
          fn()
        })
      }
      function 第二件事(){
        return new Promise(fn=>{
          第二件事的内容
          fn()
        })
      }
      function 第三件事(){
        第三件事的内容
      }

    调用时:

    第一件事()//return Promise(fn)
      .then(第二件事)//return Promise(fn)
      .then(第三件事)

    鄙视题:

    1. 将类数组对象复制为数组:
      var arr2=Array.prototype.slice.call(arguments)
      将类数组对象复制为数组,并选取指定位置的剩余元素
      var arr2= Array.prototype.slice.call(arguments,starti)

      至关于arguments.slice(starti)

      其实更简单的: var arr2= [].slice.call(arguments,starti)

    2. promise中的错误处理:
      其实: new Promise(可接收2件事)

      .then(   )  .catch(    )

      new Promise((正常函数,出错函数)=>{

      若是顺利执行:
        调用正常()
      不然
        调用出错()

      })

    3. 等待多个任务完成
      前提: 每一个任务都必须都返回Promise
      如何: Promise.all([

      task1(), task2(),...
       ]).then(()=>{全部任务完成后才执行的任务})

    1. 47
    相关文章
    相关标签/搜索