在JS中,變量的定義并不是以代碼塊作為作用域的。而是以函數作為作用域。也就是說,如果變量是在某個函數中定義的,那么它在函數以外的地方是不可見的。
在JS總,全局變量指的是定義在所有函數之外的變量,局部變量則是定義在函數內的變量,函數內的代碼可以調用全局變量,反之則不行。
比如說:
```
>>> var global = 1;
undefined
>>> function f(){
... var local = 2;
... global++;
... return global;
... }
undefined
>>> f();
2
>>> f();
3
>>> local;
Exception: ReferenceError: Can't find variable: local
```
- 函數f()可以訪問變量global
- 在函數f()以外,變量local是不存在的
如果我們聲明一個變量時沒有使用var語句,默認是全局變量
```
>>> function f(){
... local = 2;
... }
undefined
>>> local;
Exception: ReferenceError: Can't find variable: local
>>> f();
undefined
>>> local;
2
```
在實際開發中:
- 盡量將全局變量的數量減到最低,以避免命名沖突。如果有兩個人在同一段腳本的不同函數中使用了相同的全局變量名,就很容易導致不可預測的結果和難以察覺的bug。
- 最哈總是使用var語句來聲明變量
- 可以考慮使用“單一 var”模式,也就是在函數體內第一行使用var來定義這個作用域中的所需的變量
變量提升
```
var a = 123;
function f(){
alert(a);
var a = 1;
alert(a);
}
f();
```
第一次彈出undefined,第二次彈出1.
因為函數域使用優先于全局域,所以局部變量a會覆蓋所有與他同名的全局變量,盡管alert()第一次被調用時,a還沒有被正式定義,但該變量本身已經存在與本地空間了。這種特殊的現象我們叫做提升(hoisting)。
這個概念很重要,也就是說,當JS執行過程中進入新的函數時,這個函數內被聲明的所有變量都會被提升。
被提升的只有變量的聲明,與之相關的賦值操作并不會被提升。比如說剛才的demo中,局部變兩本書被提升到了函數最開始處,但并沒有在開始處就被賦值1。
上面的demo可以改成:
```
var a = 123;
function f(){
var a;
alert(a);
var a = 1;
alert(a);
}
f();
```
- 前言
- 第1章 面向對象的JavaScript
- 1.6 面向對象的程序設計
- 1.6.1 對象
- 1.6.2 類
- 1.6.3 封裝
- 1.6.4 聚合
- 1.6.5 繼承
- 1.6.6 多態
- 1.7 OOP小結
- 第2章 基本數據類型、數組、循環及條件表達式
- 2.1 變量
- 2.2 操作符
- 2.3 基本數據類型
- 2.3.1 查看類型操作符
- 2.3.2 數字
- 2.3.3 字符串
- 2.3.3.1 字符串轉換
- 2.3.3.2 特殊字符串
- 2.3.4 布爾值
- 2.3.4.1 邏輯運算符
- 2.3.4.2 操作符優先級
- 2.3.4.3 惰性求值
- 2.3.4.4 比較運算符
- 2.3.5 undefined與null
- 2.4 基本數據類型綜述
- 2.5 數組
- 2.5.1 增加、更新數組元素
- 2.5.2 刪除元素
- 2.5.3 數組的數組
- 2.6 條件與循環
- 2.6.1 if條件表達式
- 2.6.1.1 三元運算符
- 2.6.1.2 switch語句
- 2.6.2 else語句
- 2.6.3 代碼塊
- 2.6.4 檢查變量是否存在
- 2.6.5 循環
- 2.6.5.1 while循環
- 2.6.5.2 do-while循環
- 2.6.5.3 for循環
- 2.6.5.4 for-in循環
- 2.7 注釋
- 第2章 面試題
- 第2章 面試題及解答
- 第3章 函數
- 主要內容
- 3.1 什么是函數
- 3.1.1 調用函數
- 3.1.2 參數
- 3.2 預定義函數
- 3.2.1 parseInt
- 3.2.2 parseFloat
- 3.2.3 isNaN
- 3.2.4 ifFinite
- 3.2.5 URI的編碼與反編碼
- 3.2.6 eval
- 3.2.7 alert
- 3.3 變量的作用域
- 3.4 函數也是數據
- 3.4.1 匿名函數
- 3.4.2 回調函數
- 3.4.3 回調示例
- 3.4.4 既時函數
- 3.4.5 內部(私有)函數
- 3.4.6 返回函數的函數
- 3.4.7 能重寫自己的函數
- 3.5 閉包
- 3.5.1 作用域鏈
- 3.5.2 利用閉包突破作用域鏈
- 3.5.3 getter與setter
- 3.5.4 迭代器
- 第3章 面試題
- 第3章 面試題及解答
- 第4章 對象
- 4.1 從數組到對象
- 4.1.1 元素、屬性、方法與成員
- 4.1.2 哈希表、關聯型數組
- 4.1.3 訪問對象屬性
- 4.1.4 調用對象方法
- 4.1.5 修改屬性與方法
- 4.1.6 使用this值
- 4.1.7 構造器函數
- 4.1.8 全局對象
- 4.1.9 構造器屬性
- 4.1.10 instanceof操作符
- 4.1.11 返回對象的函數
- 4.1.12 傳遞對象
- 4.1.13 比較對象
- 4.1.14 Webkit控制臺中的對象
- 4.2 內建對象
- 4.2.1 Object
- 4.2.2 Array
- 4.2.3 Function
- 第8章 編程模式與設計模式
- 8.1 編程模式
- 8.1.1 行為隔離
- 8.1.2 命名空間