趁熱打鐵,今天簡單談一談作用域和閉包,老規矩請看面試題:
1.說一下對變量提升的理解
2.說明this幾種不同的使用場景
3.創建10個<a>標簽,點擊時彈出對應的序號
4.如何理解作用域
5.實際開發中閉包的使用
知識點:執行上下文? ? this? ? 作用域? ? 作用域鏈? ? 閉包
1.執行上下文
? ? 范圍:一段<script>或一個函數
? ??一段<script>:變量定義? ? 函數聲明? ?(會先被讀取)
? ? 函數:變量定義? ? 函數聲明? ? this? ? arguments(會先被讀取),注意函數聲明(function abc(){})和函數表達式(var abc = function (){})的區別
? ? 例1:????console.log(a)? ? ?????var? a = 100? ? ? //? ?undefined
? ? 例2:????a? ?= 100? ? ?console.log(a)? ? ? var? a??????????//? ?100?
? ? 例3:????fn('zhangsan')? ? //? ? ? ?zhangsan? ?20
? ? function fn(name) {
? ? ? ? age = 20
? ? ? ? console.log(name,age)? ? ? ? ?
? ? ? ? var age? ?
????}
2.? ? this
this要在執行時才能確認值,定義時無法確認,具體如下:
this指向:a? ? 構造函數中執行? ?this指向空對象,給this賦值
? ? ? ? ? ? ? ? b? ? 作為對象屬性賦值? ? 指向這個對象
? ? ? ? ? ? ? ? c? ? 普通函數中執行? ? ? ? 指向window
? ? ? ? ? ? ? ? d? ? call? apply? bind中使用? fn.call({x:100},'abc');fn函數中的this就是傳入的{x:100}
3? ? 作用域
3.1????JS中沒有塊級作用域 if (true) { var a = 100};? console.log(a)? ?//? ?100? 仍然能打印出a的值
3.2? ? 函數作用域、全局作用域(函數作用域是封閉的,不會受到外邊變量影響)
? ? ? ? ?var a = 200;
? ? ? ? ?function? fn() {
? ? ? ? ? ? var a = 100;
? ? ? ? ? ? console.log(a)
????????}
? ? ? ? console.log(a)? ?//? ?200
? ? ? ? fn();? ?//? ? 100? ? ? ??
3.3? ? 作用域鏈
? ? ? ? var a = 100;
? ? ? ? function fn() {
? ? ? ? ? ? //? ?當前作用域沒有定義的變量,即自由變量,去父級作用域查找
? ? ? ? ? ? console.log(a)
????????}
? ? ? ? fn();? //? ? 100
? ? ? ? 父級作用域:函數被定義的作用域,不是被執行時的作用域
上圖中以console.log(a)為例講一下。在F2函數體中沒有a這個變量,那么去它的父級作用域查找,F2是在F1函數體中被定義的(注意哦,是被定義的作用域不是執行的作用域),其中只定義了b變量,所以繼續向上找,F1是在全局被定義的,全局定義了變量a,所以a打印出來是100;
3.4? ? 閉包的使用場景
a? ? 函數作為返回值
? ? ? ? function F1() {
? ? ? ? ? ? var a = 100;
? ? ? ? ? ? return function () {
? ? ? ? ? ? ? ? console.log(a)
????????????}
????????}
? ? ? ? var f1 = F1();
? ? ? ? var a = 200;
? ? ? ? f1();? ? //? ?100? ?自由變量去父級作用域查找? 全局的a=200無用
b? ? 函數作為參數傳遞
?????function F1() {? ??????
????????var a = 100;
? ? ? ? ? ? return function () {
????????????????console.log(a)
????????????}
? ? ? }
? ? ? ? var f1 = F1();
? ? ? ? function F2(fn) {
? ? ? ? ? ? var a = 200;
? ? ? ? ? ? fn();
????????}
? ? ? ? F2(f1);? //? ?打印出來的 還是100? ? 原因同上? ?自由變量去父級作用域查找? a=200無用
解答:
1.說一下對變量提升的理解
? ? 這問的就是執行上下文,變量聲明的東西,注意函數聲明和函數表達式的區別
2.說明this幾種不同的使用場景
????a? ? 構造函數中執行? ?this指向空對象,給this賦值
????b? ? 作為對象屬性賦值? ? 指向這個對象
????c? ? 普通函數中執行? ? ? ? 指向window????
? ? d? ? call? apply? bind中使用? fn.call({x:100},'abc');fn函數中的this就是傳入的{x:100}
3.創建10個<a>標簽,點擊時彈出對應的序號
? ? 這道題考的是閉包,像下邊這樣的寫法是錯的,alert出來的都是9,因為當你點擊的時候,alert(i)這個i變量是自由變量,會去父級作用域查找,父級作用域的i已經是9了。
這樣的寫法才是正確的,alert的i是自由變量,會去父級作用域查找
4.如何理解作用域
? ? a? ? 自由變量
? ? b? ? 作用域鏈,即自由變量的查找
? ? c? ? 閉包的兩個場景
5.實際開發中閉包的使用
? ? 主要用于 封裝變量? 收斂權限;用在循環中,如問題3;
下期預告:異步? ? 單線程? ?敬請期待