在學習面向對象編程的更高級的問題以前,必需要徹底理解函數的做用域和閉包,以及變量訪問編程
而後將討論參數this以及原型委託(prototype delegation),數組
這是實現面向對象編程的JavaScript最主要的兩個語言特性,最後,提到寫JavaScript類和子類的多種方法閉包
深入地理解JavaScript面向對象編程的特色,以及代碼如何在運行時影響存儲模型中的解釋器函數
這種用法描述了源代碼中的範圍,在這個範圍中可使用變量名引用變量,而不出現訪問錯誤性能
這種做用域的具體規則是 即使不運行代碼,也很容易理解,由於它涉及到代碼中不一樣變量名有意義的區域學習
全局做用域被多個不一樣文件共享,使得程序的任意部分均可以和另外一部分交互this
在全局做用域中聲明變量以後,就能夠在該詞法做用域的任意位置引用這個變量了prototype
每當定義一個函數,就會建立一個新的詞法做用域,可是比其外層的詞法做用域,要多一些限制對象
雖然你仍然能夠訪問,其外層做用域中的變量,也能夠訪問在這個內層做用域中定義的變量,blog
但該內層做用域中的變量,沒法從該做用域以外訪問。
在函數這對花括號範圍以外,引用內層做用域中的局部變量,將致使錯誤
請注意一個容易出錯的地方,JavaScript容許給未聲明的變量賦值,
它將被自動添加到全局做用域,而非你賦值的這個做用域
這是很很差的行爲,由於漏寫var關鍵字,一般是由疏忽形成,而非故意爲之
即便你是刻意爲之,其餘人閱讀代碼時,也會很是困惑,他們會認爲這個是錯誤疏忽致使的
因此請記住,在任何詞法做用域中聲明變量時,務必加上var關鍵詞。
如何區分不一樣的詞法做用域
如何控制它們的規則
當程序運行的時候,就建立一個用於保存變量和變量值的存儲系統,
這些內存中的做用域結構就被稱爲執行環境
執行環境它是在代碼運行時才被建立,而不是在代碼被輸入時,
規則能夠控制在程序執行過程當中的不一樣點能夠訪問哪些變量
程序運行時,將會建立內部數據存儲,以記錄可供不一樣函數對象訪問的全部變量
因爲函數的每一次運行,都徹底獨立於此前的任何一次運行,每次函數運行時,就會建立一個新的運行環境
所以每一個詞法做用域在運行的過程當中,可能會建立多個內存做用域,也可能一個都沒有,這徹底取決於此函數運行了多少次
解釋器(interpreter)就開始配置執行環境(execution environment)
第一步是在內存中,建立一個全局做用域環境,以保存全部全局變量,
在這裏,解釋器爲全局做用域建立一個存儲系統
此時這裏就是解釋器當前的執行環境,也就是說這是解釋器開始查找變量的區域
解釋器會在執行環境中,建立一個新的鍵值映射,以記錄變量名對應的值
如今這個執行環境看起來像是鍵值對的集合,這與對象有點相似,
會讓人誤覺得內存做用域和內存對象是一回事
這個類似之處很是具備欺騙性,由於他們都是由解釋器徹底分開保存,
並且,在訪問執行環境時的不少限制,在訪問對象時並不存在
除了它們長得有點相似,其實它們存在於徹底不一樣的世界,幾乎永不交互
舉例說明一下,你毫不可能存儲一個包含不少環境的數組,但卻能夠存儲一個包含不少對象的數組
你沒法像在對象中遍歷鍵那樣,在執行環境中去遍歷變量名,所以,雖然它們都是鍵值數據存儲結構
但你只能使用徹底不一樣的方式與它們交互
JavaScript開發者會常用閉包, 簡單來講,每一個函數均可以訪問,其外圍做用域中的全部變量
閉包是指 一些函數經過某種方式,能夠隨時被訪問,即便它的外部代碼已經執行完畢
來了解閉包是如何工做,以及咱們該如何使用閉包
在newSaga調用完成後仍然能夠訪問函數saga?
將saga傳入setTimeout
在newSaga中返回saga
saga保存爲某個全局變量
以上三種方法均可以幫助咱們在函數newSaga執行完畢後,仍然能訪問函數saga