## 作用域
**1.1 作用域**
幾乎所有的編程語言都有作用域的概念,簡單的說,作用域就是變量與函數的可訪問范圍,即作用域控制著變量與函數的可見性和生命周期。
作用域有全局作用域和局部作用域(一般是在函數內)之分。
**1.1.1 全局作用域**
在代碼中任何地方都能訪問到的對象擁有全局作用域。
一般來說,擁有全局作用域有以下幾種情況:
**(1)在最外層的函數和在最外層函數外面定義的變量擁有全局作用域**
例子:
```
var name = 'tg';
function test(){
var name2 = 'tg';
}
```
在上面的例子中,變量name和函數test()就擁有全局作用域
**(2)所有未定義而直接賦值(不用var關鍵字聲明)的變量被自動聲明為擁有全局作用域**
```
funciton test(){
var age = 10;
name = 'tg';
}
test();
console.log(age); // 會報錯undefined
console.log(name); // "tg"
```
變量name擁有全局作用域,而age在函數外面是無法訪問到的
**(3)所有window對象的屬性擁有全局作用域**
window對象的內置屬性都由擁有全局作用域,比如window.location、Date對象等
**1.1.2 局部作用域**
局部作用域不像全局作用域,它被限定在一個范圍內,最常見的局部作用域就是在函數內部,我們也稱為**函數作用域**。
**函數作用域**是指變量能夠被使用的代碼區間。超出作用域的變量值一般為undefined,或者被其他同名變量值所覆蓋。
```
funciton test(){
var age = 10;
console.log(age);
}
test(); // 10
console.log(age); // 會報錯undefined
```
在上面的例子中,在函數外面是無法訪問到變量age的,但在函數內部是可以訪問的。
要記住,對于變量或函數,它的作用域取決于定義時的作用域,而不是在調用它的作用域中。
**1.2 作用域鏈**
在ES 5中,將作用域鏈稱為**詞法環境**。
當代碼在一個作用域中執行時,會創建變量對象的一個作用域鏈(scope chain)。
作用域鏈的用途:保證對執行環境有權訪問的所有變量和函數的有序訪問。
作用域鏈的前端,始終都是當前執行的代碼所在作用域的變量對象。如果這個環境是函數,則將其活動對象作為變量對象,然后對于每一個函數的形參,都命名為該活動對象的命名屬性。
活動對象在最開始只包含一個變量,即arguments對象(在全局環境中是不存在的)。
看一個例子:
```
var name = 'p';
function test(){
var name = 'tg';
function get(){
console.log(name);
}
get();
}
test(); // "tg"
```
當執行get()時,將創建函數get()的執行環境(調用對象),并將該對象置于作用域鏈的前端(開頭),然后將函數test()的調用對象鏈接在之后,最后是全局對象,然后從作用域鏈的前端開始查找標識符name,很顯然,變量name的值是"tg";
作用域鏈:get() -> test() -> window
每次進入一個新的作用域,都會創建一個用于搜索變量和函數的作用域鏈。
函數的局部變量不僅有權訪問函數作用域中的變量,而且有權訪問其他包含(父)環境,乃至全局作用域。但是全局作用域只能訪問在全局作用域中定義的變量和函數,不能直接訪問局部作用域中的任何數據。
變量的作用域有助于確定應該何時釋放內存。
**1.3 JavaScript沒有塊級作用域**
JavaScript中并沒有塊級作用域。也就是說,對于if、for、while、switch等塊結構是沒有作用域的。
```
if(true){
var name = 'tg';
}
console.log(name); // "tg"
```
在if語句里定義了一個name變量,但它并不會向在函數內那樣,但函數執行結束后就銷毀,而是會一直存在,因為它被添加到了當前的執行環境(也就是全局環境)中。
對于for循環也是一樣:
```
for(var i = 0; i < 10; i++){
//循環體
}
console.log(i); // 10
```
**(1)聲明變量**
使用var聲明的變量會自動被添加到最接近的環境中,比如在函數內部,最接近的環境就是函數的局部環境。如果初始化變量沒有使用var聲明,會自動被添加到全局環境中。
**(2)查詢標識符**
標識符的查詢規則是:逐級向上查詢,如果在局部環境中找到了該標識符,搜索過程就停止,變量就緒,否則,會繼續向上查詢,直到全局環境的變量對象,如果在全局環境中也沒有找到這個標識符,就表示該變量尚未聲明(通常會報錯)。
```
var name = 'tg2';
function test(){
var name = 'tg';
console.log(name); // "tg"
}
test();
```
在上面的例子中,在函數內部已經找到了name標識符,所以返回的是"tg"
- 前言
- JavaScript簡介
- 基本概念
- 語法
- 數據類型
- 運算符
- 表達式
- 語句
- 對象
- 數組
- 函數
- 引用類型(對象)
- Object對象
- Array對象
- Date對象
- RegExp對象
- 基本包裝類型(Boolean、Number、String)
- 單體內置對象(Global、Math)
- console對象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應用
- 客戶端存儲(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測設備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向對象的程序設計
- 概述
- this關鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯誤處理機制
- JavaScript開發技巧合集
- 編程風格
- 垃圾回收機制