前端知識點總結——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
    相關文章
    相關標籤/搜索