作用域和作用域鏈
1.作用域
理解:
- 就是一塊地盤,一個代碼所在的區域
- 它是靜態的(相對於上下文對象),在編寫代碼的時候就已經確定
分類:
- 全局作用域
- 局部作用域
- 塊作用域(ES6)
作用:
- 隔離變量,不同作用域下同名變量不會有衝突
2.作用域和執行上下文
1).區別1
- 全局作用域之外,每個函數都會創建自己的作用域,作用域在函數定義時就已經確定,而不是在函數調用時
- 全局執行上下文環境是在全局作用域確定之後,js代碼馬上執行之前創建
- 函數執行上下文是在調用函數時,函數體代碼執行之前創建
2).區別2
- 作用域是靜態的,只要函數定義好了就會一直存在,且不會再變化
- 執行上下文環境是動態的,調用函數時創建,函數調用結束時上下文環境會被動態釋放
3).聯繫
- 執行上下文環境(對象)是從屬於所在的作用域
- 全局上下文環境---->全局作用域
- 函數上下文環境---->對應的函數使用域
3.作用域鏈
1).理解
- 多個上下級關係的作用域形成的鏈,它的方向是從下向上的(從內到外)
- 查找變量時就是沿着作用域鏈來查找的
2).查找一個變量的規則
- 在當前作用域下的執行上下文中查找對應的屬性,如果有直接返回,否則進入2
- 在上一級作用域的執行上下文查找對應的屬性,如果有直接返回,否則進入3
- 再次執行2的相同操作,直到全局作用域,如果還找不到就拋出找不到的異常
圖解:
面試題:
1).
<script type="text/javascript">
var x = 10;
function fn() {
console.log(x) // 10
}
function show(f) {
var x = 20
f()
}
show(fn)
</script>
2).
<script type="text/javascript">
var fn = function () {
console.log(fn) //輸出fn函數
}
fn()
var obj = {
fn2: function () {
console.log(fn2) //報錯 fn2未定義
}
}
obj.fn2()
</script>
閉包
1.閉包的理解
1).如何產生閉包?
- 當一個嵌套的內部(子)函數引用了嵌套的外部(父)函數的變量(函數)時,就產生了閉包
2).閉包到底是什麼?
- 理解一:閉包是嵌套的內部函數
- 理解二:包含被引用變量(函數)的對象
- 注意:閉包存在於嵌套的內部函數中
3).產生閉包的條件?
- 函數嵌套
- 內部函數引用了外部函數的數據(變量/函數)
2.常見的閉包
- 將函數作爲另一個函數的返回值
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() // 3
f() // 4
- 將函數作爲實參傳遞給另一個函數調用
function showDelay(msg, time) {
setTimeout(function () {
alert(msg)
}, time)
}
showDelay('hello', 1000)
3.閉包的作用
- 延長了局部變量的生命週期
- 在外部能夠間接的操作內部的變量
4.閉包的生命週期
- 產生:在嵌套內部函數定義執行完時就產生了(不是在調用)
- 死亡:在嵌套的內部函數成爲垃圾對象時
<script type="text/javascript">
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
// 問題1:此時閉包產生了嗎? 已產生
var f = fn1()
// 問題2:此時閉包釋放了嗎? 沒有
f()
f()
// 問題3:此時閉包釋放回收了嗎? 沒有
// 問題4:如何讓閉包釋放回收呢? f = null
</script>
5.閉包的應用
自定義JS模塊
- 具有特定功能的js文件
- 將所有的數據和功能都封裝在一個函數內部(私有的)
- 只向外部暴露一個包含n個方法的對象或函數
- 模塊的使用者,只需要通過模塊暴露的對象調用方法來實現對應的功能
6.閉包的缺點以及解決
缺點
- 函數執行完後,函數內的局部變量沒有釋放,佔用內存時間會變長
- 容易造成內存泄露
解決
- 能不用閉包就不用
- 及時釋放
內存溢出與內存泄露
1.內存溢出
- 一種程序運行出現的錯誤
- 當程序運行需要的內存超過了剩餘的內存時,就會拋出內存溢出的錯誤
2.內存泄露
- 佔用的內存沒有及時釋放
- 內存泄露積累多了就容易導致內存溢出
- 常見的內存泄露:
- 意外的全局變量
- 沒有及時清理的計時器或回調函數
- 閉包