1. 程式人生 > >【JavaScript高階】14、函式高階筆記

【JavaScript高階】14、函式高階筆記

原型與原型鏈

  • 所有函式都有一個特別的屬性:
    • prototype : 顯式原型屬性
  • 所有例項物件都有一個特別的屬性:
    • __proto__ : 隱式原型屬性
  • 顯式原型與隱式原型的關係
    • 函式的prototype: 定義函式時被自動賦值, 值預設為{}, 即用為原型物件
    • 例項物件的__proto__: 在建立例項物件時被自動新增, 並賦值為建構函式的prototype值
    • 原型物件即為當前例項物件的父物件
  • 原型鏈
    • 所有的例項物件都有__proto__屬性, 它指向的就是原型物件
    • 這樣通過__proto__屬性就形成了一個鏈的結構---->原型鏈
    • 當查詢物件內部的屬性/方法時, js引擎自動沿著這個原型鏈查詢
    • 當給物件屬性賦值時不會使用原型鏈, 而只是在當前物件中進行操作

執行上下文與執行上下文棧

  • 變數提升與函式提升
    • 變數提升: 在變數定義語句之前, 就可以訪問到這個變數(undefined)
    • 函式提升: 在函式定義語句之前, 就執行該函式
    • 先有變數提升, 再有函式提升
  • 理解
    • 執行上下文: 由js引擎自動建立的物件, 包含對應作用域中的所有變數屬性
    • 執行上下文棧: 用來管理產生的多個執行上下文
  • 分類:
    • 全域性: window
    • 函式: 對程式設計師來說是透明的
  • 生命週期
    • 全域性 : 準備執行全域性程式碼前產生, 當頁面重新整理/關閉頁面時死亡
    • 函式 : 呼叫函式時產生, 函式執行完時死亡
  • 包含哪些屬性:
    • 全域性 :
      • 用var定義的全域性變數 ==>undefined
      • 使用function宣告的函式 ===>function
      • this ===>window
    • 函式
      • 用var定義的區域性變數 ==>undefined
      • 使用function宣告的函式 ===>function
      • this ===> 呼叫函式的物件, 如果沒有指定就是window
      • 形參變數 ===>對應實參值
      • arguments ===>實參列表的偽陣列
  • 執行上下文建立和初始化的過程
    • 全域性:
      • 在全域性程式碼執行前最先建立一個全域性執行上下文(window)
      • 收集一些全域性變數, 並初始化
      • 將這些變數設定為window的屬性
    • 函式:
      • 在呼叫函式時, 在執行函式體之前先建立一個函式執行上下文
      • 收集一些區域性變數, 並初始化
      • 將這些變數設定為執行上下文的屬性

作用域與作用域鏈

  • 理解:
    • 作用域: 一塊程式碼區域, 在編碼時就確定了, 不會再變化
    • 作用域鏈: 多個巢狀的作用域形成的由內向外的結構, 用於查詢變數
  • 分類:
    • 全域性
    • 函式
    • js沒有塊作用域(在ES6之前)
  • 作用
    • 作用域: 隔離變數, 可以在不同作用域定義同名的變數不衝突
    • 作用域鏈: 查詢變數
  • 區別作用域與執行上下文
    • 作用域: 靜態的, 編碼時就確定了(不是在執行時), 一旦確定就不會變化了
    • 執行上下文: 動態的, 執行程式碼時動態建立, 當執行結束消失
    • 聯絡: 執行上下文環境是在對應的作用域中的

閉包

  • 理解:
    • 當巢狀的內部函式引用了外部函式的變數時就產生了閉包
    • 通過chrome工具得知: 閉包本質是內部函式中的一個物件, 這個物件中包含引用的變數屬性
  • 作用:
    • 延長區域性變數的生命週期
    • 讓函式外部能操作內部的區域性變數
  • 寫一個閉包程式
    function fn1() {
      var a = 2;
      function fn2() {
        a++;
        console.log(a);
      }
      return fn2;
    }
    var f = fn1();
    f();
    f();
    
  • 閉包應用:
    • 模組化: 封裝一些資料以及操作資料的函式, 向外暴露一些行為
    • 迴圈遍歷加監聽
    • JS框架(jQuery)大量使用了閉包
  • 缺點:
    • 變數佔用記憶體的時間可能會過長
    • 可能導致記憶體洩露
    • 解決:
      • 及時釋放 : f = null; //讓內部函式物件成為垃圾物件

記憶體溢位與記憶體洩露

  1. 記憶體溢位
  • 一種程式執行出現的錯誤
  • 當程式執行需要的記憶體超過了剩餘的記憶體時, 就出丟擲記憶體溢位的錯誤
  1. 記憶體洩露
  • 佔用的記憶體沒有及時釋放
  • 記憶體洩露積累多了就容易導致記憶體溢位
  • 常見的記憶體洩露:
    • 意外的全域性變數
    • 沒有及時清理的計時器或回撥函式
    • 閉包