JS函數高級

原型與原型鏈

  • 所有函數都有一個特別的屬性:
    • 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. 內存泄露
  • 佔用的內存沒有及時釋放
  • 內存泄露積累多了就容易導致內存溢出
  • 常見的內存泄露:
    • 意外的全局變量
    • 沒有及時清理的計時器或回調函數
    • 閉包
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章