原型與原型鏈 所有函數都有一個特別的屬性: prototype : 顯式原型屬性 所有實例對象都有一個特別的屬性: __proto__ : 隱式原型屬性 顯式原型與隱式原型的關係 函數的prototype: 定義函數時被自動賦值, 值預設為, 即用為原型對象 實例對象的__proto__: 在創建實 ...
原型與原型鏈
- 所有函數都有一個特別的屬性:
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; //讓內部函數對象成為垃圾對象
記憶體溢出與記憶體泄露
- 記憶體溢出
- 一種程式運行出現的錯誤
- 當程式運行需要的記憶體超過了剩餘的記憶體時, 就出拋出記憶體溢出的錯誤
- 記憶體泄露
- 占用的記憶體沒有及時釋放
- 記憶體泄露積累多了就容易導致記憶體溢出
- 常見的記憶體泄露:
- 意外的全局變數
- 沒有及時清理的計時器或回調函數
- 閉包