#### 函數作用域
由于bar中的i沒有用到var來聲明,導致i的聲明自動跑到了foo的作用域中,與for循環中的i相互覆蓋。導致執行foo函數的時候i一直被賦予3,無限循環下去
```
function foo(){
function bar(a) {
i = 3;
console.log(a + i);
}
for(var i = 0; i< 10; i++){
bar(i * 2);
}
}
```
區分函數表達式和函數聲明:function關鍵字是否是聲明語句中的第一個詞(不僅僅是一行,而是整個聲明中的位置),是-->函數聲明,否-->函數表達式。立即執行函數前面有(,所以也是函數表達式。函數聲明和函數表達式之間最重要的區別就是它們的名稱標識符將會綁定在何處。
```
var f1 = function(){...}
function f2(){...}
//二者均被綁定在所在的作用域中,可以直接通過f1()、f2()來調用
(function(){...})()
//被綁定在了自身里,只能在...中訪問它
```
函數表達式可以是匿名的,而函數聲明不可以匿名
```
setTimeout(function() {
console.log(1);
}, 1000)
//function關鍵字并不位于整個聲明語句的第一個詞,所以該function是表達式,是匿名表達式,除了function內部外,任何地方都不能使用它
```
始終給函數一個名字是最佳實踐,這有利于調試和維護
```
setTimeout(function timeoutHandler() {
console.log(1);
}, 1000)
```
```
(function(){})()
(function(){}())
//二者在功能上是一致的
```
#### 塊作用域
```
for(var i = 0; i < 10; i++){
console.log(i);
}
```
i會被綁在外部作用域中,這也是為什么
```
for(var i = 0; i < 10; i++){
element[i].onClick = function(){
console.log(i)
}
}
```
最后的結果都是11的原因,因為click事件是異步函數,當你點擊元素的時候for早就已經結束了,此時的i是11。
try/catch的catch會創建塊級作用域,內部的變量只能在catch中使用。
塊級作用域有利于垃圾回收:
點擊事件并不需要data數據,按理說process執行完后data就會被回收,但由于click函數形成了覆蓋整個作用域的閉包,導致該作用域內的一切資源都可能無法回收。
```
function process(data){...}
var data = {...}
process(data);
element.onClick = function(){...}
```
使用塊級作用域就可以解決該問題,告訴引擎該變量沒必要再保存了
```
function process(data){...}
{
let data = {...}
process(data);
}
element.onClick = function(){...}
```
- 你不知道的JS上
- 第一部分 第三章 函數作用域和塊作用域
- 第一部分 第四章 提升
- 第一部分 第五章 閉包
- 第二部分 第一章 關于this
- 第二部分 第二章 this全面解析
- 第二部分 第三章 對象
- 第二部分 第五章 原型
- 第二部分 第六章 行為委托
- 你不知道的JS中
- 第一部分 第二章 值
- 第一部分 第三章 原生函數
- 第一部分 第四章 強制類型轉換
- 第一部分 第五章 語法
- 第二部分 第一章 異步
- 第二部分 第三章 Promise
- 第二部分 第四章 生成器
- 第二部分 第五章 性能
- 你不知道的JS下
- 第一部分 總結
- 第二部分 第二章 語法
- 第二部分 第三章 代碼組織
- 第二部分 第四章 Promise
- 第二部分 第五章 集合
- 第二部分 第六章 新增API
- 第二部分 第七章 元編程
- 第二部分 第八章 ES6之后