1. 程式人生 > >理解javascript作用域及hosting機制

理解javascript作用域及hosting機制

tro 理解 cti 顯示 定義變量 可見 變量聲明 之前 為什麽

在javascript中, 理解變量的作用域以及變量提升是非常有必要的,特別是對於初學者,很容易莫名地就掉坑裏。

一、javaScript作用域

在C語言中,一對花括號{}代表一個獨立的作用域,我們稱之為塊級作用域。一個塊級作用域中,只作用於該塊的變量可以被聲明,只會影響快內而不會影響塊外面的作用域。javaScript沒有塊級作用域,只有全局作用域和函數作用域。

全局作用域其實是全局對象的作用域,任意地方都可以訪問到。函數對象作用域跟C的局部變量作用域是不同的,它的作用域是整個函數範圍,在函數內聲明的所有變量在函數體內始終是可見的。

下面我們吃些栗子來加深理解:

栗子代碼1:

var x=‘我是只鍋‘;//
聲明一個全局變量x console.log(x);//‘我是只鍋’ if(1){   var x=‘我是只灰色的鍋‘;   console.log(x);//‘我是只灰色的鍋’ } console.log(x);//‘我是只灰色的鍋’

在if語句裏面改變了變量x的值,全局變量x也就改變了,說明{}沒有建立新的作用域,而是處於全局作用域中的,由此可見javascript跟 C的作用域是不一樣的。對於全局作用域的變量,無論是在if語句內還是函數內都可以訪問到;

栗子代碼2:

function a(){
    var arg=‘我是只鍋‘;
}
console.log(arg);//瀏覽器報錯:arg is not defined

arg變量是在函數a內聲明的,函數外沒有聲明,無法獲取到arg變量,所以瀏覽器報錯。說明函數對象作用域,只有在函數體內才可以訪問,而函數體外是不能訪問。

栗子代碼3:

var arg=‘我是只鍋‘;
function a(){
    console.log(arg);//undefined
    var arg=‘我是只灰色的鍋‘;
    console.log(arg);//‘我是只灰色的鍋’
}
a();

這裏應該很多童靴可能會認為第三行會輸出“我是只鍋”,因為代碼還沒有執行到var語句聲明arg的地方。然而並非如此,這到底是為什麽呢?這裏就引申出javascript作用域的一個特性:hosting機制。

二、hosting機制

所謂的hoisting,也就是變量提升的概念。變量提升即將變量聲明提升到它所在作用域的最開始的部分。在javaScript中,變量和函數的聲明會提升到最頂部執行。

由於函數作用域的特性,局部變量在整個函數體內始終是有定義的。因此在上面的栗子3中,函數體內局部變量arg遮蓋了同名全局變量arg。不過,只是聲明提前了,賦值執行是沒有被提前的,所以第三行會輸出undefined。由此,上面的過程相當於這樣:

var arg=‘我是只鍋‘;
function a(){
    var arg;
    console.log(arg);//undefined
    arg=‘我是只灰色的鍋‘;
    console.log(arg);//‘我是只灰色的鍋’
}
a();

下面我們接著吃些栗子來深剖一下hosting的特點:

(1)函數聲明提升高於變量聲明

栗子代碼1:

console.log(typeof a);//function
var a;
function a(){
    ...
}

栗子代碼2:

console.log(typeof a);//function
function a(){
    ...
}
var a;

同時定義變量a和函數a,無論是先定義函數還是後定義函數,最後a顯示的都是函數,證明function的優先級高於var。

(2)匿名函數不會向上提升

栗子代碼:

console.log(typeof a);//undefined
var a=function (){
    ...
}

匿名函數這種形式其實就是var變量的聲明定義,因此第一行輸出結果為undefined,應該是可以理解的。

(3)不同代碼塊中的函數互不影響

栗子代碼:

<script>//代碼塊1
    console.log(typeof a);//undefined
    var a=function (){
        ...
    }
</script>

<script>//代碼塊2
    function a(){
        ...
    }
</script>

代碼塊1中的a,輸出的是undefined,說明代碼塊2的函數a沒有被提前到代碼塊1之前,由此可見不同代碼塊之間函數是互不影響的。

理解javascript作用域及hosting機制