[TOC]
# 變量的值、作用域和內存問題
JavaScript變量松散類型的本質,決定了它只是在特定時間用于保存特定值的一個名字。由于不存在定義某個變量必須保存何種數據類型值的規則,變量的值及其數據類型可以在腳本的生命周內改變。
## 4.1 基本類型和引用類型的值
**ECMAScript中的所有參數傳遞的都是值,不可能通過引用傳遞參數。**
ECMAScript變量可能包含兩種不同數據類型的值:基本類型值和引用類型之。**基本類型值**源自于基本數據類型,**引用類型值**則指那些可能由多個值構成的對象。
兩種數據類型的值的**特點**:
* 基本類型值在內存中占據固定大小的空間,因此被保存在**棧內存**中;
* 從一個變量向另一個變量**復制***基本類型*的值,會創建這個值的一個**副本**;
* 引用類型的值是**對象**,保存在**堆內存**中;
* 包含引用類型的變量實際上包含的并不是對象本身,而是一個指向該對象的**指針**;
* 從一個變量向另一個變量復制*引用類型*的值,復制的其實是指針,因此兩個變量最終都**指向同一個對象**;
確定一個值是哪個基本類型可以用`typeof`操作符,而確定一個值是哪種引用類型可以使用`instanceof`操作符,如:
~~~
alert(person instanceof Object); //變量person是Object嗎?
alert(colors instanceof Array); //變量colors是Array嗎?
~~~
## 4.2 執行環境及作用域
所有變量(包括基本類型和引用類型)都存在于一個**執行環境**(也成為**作用域**)當中,這個執行環境決定了變量的生命周期,以及哪一部分代碼可以訪問其中的變量。
某個執行環境中的所有代碼執行完畢后,該環境被銷毀,保存在其中的所有變量和函數定義也隨之銷毀(全局執行環境直到應用程序退出--例如關閉網頁或瀏覽器--時才會被銷毀)。
在Web瀏覽器中,全局執行環境被認為是window對象,因此所有全局變量和函數都是作為**window對象**的屬性和方法創造的。
**執行環境總結:**
* 執行環境有**全局**執行環境(也稱全局環境)和**函數**執行環境之分;
* 每次進入一個新執行環境,都會創建一個用于**搜索變量和函數**的**作用域鏈**;
* 函數的局部環境不僅有權訪問函數作用域中的變量,而且有權訪問其包含(父)環境,乃至全局環境;
* 全局環境只能訪問在全局環境中定義的變量和函數,而**不能直接訪問局部**環境中的任何數據;
* 變量的執行環境有助于確定應該**何時釋放內存**。
**延長作用域鏈**
~~~
try-catch語句的catch塊
with語句
~~~
這兩個語句都會在**作用域鏈的前端**添加一個變量對象。對with語句來說,會將指定對象添加到作用域鏈中。對catch語句來說,會創建一個新的變量對象,其中包含的是被拋出的錯誤對象的聲明。
**沒有塊作用域**
JavaScript中沒有塊級作用域,因此if語句中的變量聲明會添加到當前的執行環境(下例為全局環境)中。
在使用for語句時尤其要牢記這一差異,例如:
~~~
for (var i=0; i <10; i++) {
doSomething(i)
}
alert(i); // 10
~~~
由for語句創建的變量i即使在for循環執行結束后,依舊會存在于循環外部的執行環境中。
## 4.3 垃圾收集
JavaScript是一門具有自動垃圾收集機制的編程語言,開發人員不必關心內存分配和回收問題。
* 離開作用域的值將唄自動標記為可以回收,因此將在垃圾收集期間被刪除。
* "標記清除"是目前主流的垃圾收集算法,算法思想是給當前不使用的值加上標記,然后再回收其內存。
* "引用計數"的算法思想是跟蹤記錄所有值被引用的次數。(淘汰)當代碼中存在循環引用現象時,會導致問題。
* 解除變量的引用不僅有助于消除循環引用現象,而且對垃圾收集也有好處。為了確保有效地回收內存,應該及時解除不再使用的全局對象、全局對象屬性以及循環引用變量的引用。
- 前言
- 第一章 JavaScript簡介
- 第三章 基本概念
- 3.1-3.3 語法、關鍵字和變量
- 3.4 數據類型
- 3.5-3.6 操作符、流控制語句(暫略)
- 3.7函數
- 第四章 變量的值、作用域與內存問題
- 第五章 引用類型
- 5.1 Object類型
- 5.2 Array類型
- 5.3 Date類型
- 5.4 基本包裝類型
- 5.5 單體內置對象
- 第六章 面向對象的程序設計
- 6.1 理解對象
- 6.2 創建對象
- 6.3 繼承
- 第七章 函數
- 7.1 函數概述
- 7.2 閉包
- 7.3 私有變量
- 第八章 BOM
- 8.1 window對象
- 8.2 location對象
- 8.3 navigator、screen與history對象
- 第九章 DOM
- 9.1 節點層次
- 9.2 DOM操作技術
- 9.3 DOM擴展
- 9.4 DOM2和DOM3
- 第十章 事件
- 10.1 事件流
- 10.2 事件處理程序
- 10.3 事件對象
- 10.4 事件類型
- 第十一章 JSON
- 11.1-11.2 語法與序列化選項
- 第十二章 正則表達式
- 12.1 創建正則表達式
- 12.2-12.3 模式匹配與RegExp對象
- 第十三章 Ajax
- 13.1 XMLHttpRequest對象
- 你不知道的JavaScript
- 一、作用域與閉包
- 1.1 作用域
- 1.2 詞法作用域
- 1.3 函數作用域與塊作用域
- 1.4 提升
- 1.5 作用域閉包
- 二、this與對象原型
- 2.1 關于this
- 2.2 全面解析this
- 2.3 對象
- 2.4 混合對象“類”
- 2.5 原型
- 2.6 行為委托
- 三、類型與語法
- 3.1 類型
- 3.2 值
- 3.3 原生函數