咱們先來看看下面的例子:javascript
alert(a);//輸出:function a(){ alert('我是函數') } function a(){ alert('我是函數') }// var a = '我是變量'; alert(a); //輸出:'我是變量'
這代碼等效於:java
function a(){alert('我是函數')} var a; //hoisting alert(a); //輸出:function a(){ alert('我是函數') } a = '我是變量';//賦值 alert(a); //輸出:'我是變量'
這短短的代碼裏面其實說明了兩個問題:函數
var a;
被function a(){}
覆蓋掉了。a='我是變量'
又把function a(){}
覆蓋掉了。把一個變量添加到做用域中除有不少方法,以下:this
formal parameter
(也就是中文說的形參吧)var
聲明並賦值,好比說var a = 10;
var
聲明不賦值,好比說var a;
function
聲明,好比說function a(){};
咱們來看看他們之間的優先級:code
1.var聲明並賦值
優先級高於function聲明
這個上面已經說了。orm
2.function聲明
優先級高於formal parameter
ip
function fnTest(a){ alert(a); function a(){return "我優先"} } fnTest(100);//:function a(){return "我優先"}。能夠看出function聲明覆蓋了`formal parameter`。
3.formal parameter
優先級高於預約義變量
作用域
function fnTest(arguments){ alert(arguments); } fnTest(100);//:100。說明`formal parameter`優先級比預約義的arguments高
對比如下:io
function fnTest(a){ alert(arguments); } fnTest(100);//:[Object Arguments] {0:100,length:1}。當沒有衝突時輸出即是預約義的arguments
4.formal parameter
優先級高於var聲明不賦值
function
function fnTest(a){ alert(a); var a; } fnTest(100);//:100。很明顯,很少說
5.預約義變量
優先級高於 var聲明不賦值
function fnTest(){ alert(arguments); var arguments; } fnTest();//:[Object Arguments]。不是undefined,說明arguments沒有被var聲明覆蓋
6.var聲明不賦值
優先級高於函數外部做用域的其餘全部聲明
function fnTest(){ alert(fnTest); var fnTest; } fnTest();//:undefined。
對好比下:
function fnTest(){ // alert(fnTest); // } // fnTest(); //輸出function fnTest(){alert(fnTest);}
這也正好印證了做用域鏈查找變量的方式:在局部做用域裏查找(若找到則返回,沒必要往下繼續查找) ==> 在上一級做用域裏查找... ==> 直到全局做用域(若找不到則返回typeError)
最後看看下面的綜合例子:
function fnTest(arguments){// alert(arguments);//function arguments(){return "hello world"} var arguments = 99;// function arguments(){return "hello world"}; alert(arguments);//99 } fnTest(100);