## 原型與原型鏈
* 全部函數都有一個特別的屬性:
* `prototype` : 顯式原型屬性
* 全部實例對象都有一個特別的屬性:
* `__proto__` : 隱式原型屬性
* 顯式原型與隱式原型的關係
* 函數的prototype: 定義函數時被自動賦值, 值默認爲{}, 即用爲原型對象
* 實例對象的__proto__: 在建立實例對象時被自動添加, 並賦值爲構造函數的prototype值
* 原型對象即爲當前實例對象的父對象
* 原型鏈
* 全部的實例對象都有__proto__屬性, 它指向的就是原型對象
* 這樣經過__proto__屬性就造成了一個鏈的結構---->原型鏈
* 當查找對象內部的屬性/方法時, js引擎自動沿着這個原型鏈查找
* 當給對象屬性賦值時不會使用原型鏈, 而只是在當前對象中進行操做
## 執行上下文與執行上下文棧
* 變量提高與函數提高
* 變量提高: 在變量定義語句以前, 就能夠訪問到這個變量(undefined)
* 函數提高: 在函數定義語句以前, 就執行該函數
* 先有變量提高, 再有函數提高
* 理解
* 執行上下文: 由js引擎自動建立的對象, 包含對應做用域中的全部變量屬性
* 執行上下文棧: 用來管理產生的多個執行上下文
* 分類:
* 全局: window
* 函數: 對程序員來講是透明的
* 生命週期
* 全局 : 準備執行全局代碼前產生, 當頁面刷新/關閉頁面時死亡
* 函數 : 調用函數時產生, 函數執行完時死亡
* 包含哪些屬性:
* 全局 :
* 用var定義的全局變量 ==>undefined
* 使用function聲明的函數 ===>function
* this ===>window
* 函數
* 用var定義的局部變量 ==>undefined
* 使用function聲明的函數 ===>function
* this ===> 調用函數的對象, 若是沒有指定就是window
* 形參變量 ===>對應實參值
* arguments ===>實參列表的僞數組程序員
## 繼承模式
* 原型鏈繼承 : 獲得方法
```
function Parent(){}
Parent.prototype.test = function(){};
function Child(){}
Child.prototype = new Parent(); // 子類型的原型指向父類型實例
Child.prototype.constructor = Child
var child = new Child(); //有test()
```
* 借用構造函數 : 獲得屬性
```
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){};
function Child(xxx,yyy){
Parent.call(this, xxx);//借用構造函數 this.Parent(xxx)
}
var child = new Child('a', 'b'); //child.xxx爲'a', 但child沒有test()
```
* 組合
```
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){};
function Child(xxx,yyy){
Parent.call(this, xxx);//借用構造函數 this.Parent(xxx)
}
Child.prototype = new Parent(); //獲得test()
var child = new Child(); //child.xxx爲'a', 也有test()
```
* new一個對象背後作了些什麼?
* 建立一個空對象
* 給對象設置__proto__, 值爲構造函數對象的prototype屬性值 this.__proto__ = Fn.prototype
* 執行構造函數體(給對象添加屬性/方法)
* 執行上下文建立和初始化的過程
* 全局:
* 在全局代碼執行前最早建立一個全局執行上下文(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. 內存溢出
* 一種程序運行出現的錯誤
* 當程序運行須要的內存超過了剩餘的內存時, 就出拋出內存溢出的錯誤
2. 內存泄露
* 佔用的內存沒有及時釋放
* 內存泄露積累多了就容易致使內存溢出
* 常見的內存泄露:
* 意外的全局變量
* 沒有及時清理的計時器或回調函數
* 閉包
chrome