深刻理解變量聲明提高和函數聲明提高

變量聲明提高

轉載:http://blog.csdn.net/qq673318522/article/details/50810650函數

一、變量定義

能夠使用var定義變量,變量若是沒有賦值,那變量的初始值爲undefinedspa

二、變量做用域

變量做用域指變量起做用的範圍。變量分爲全局變量和局部變量。全局變量在全局都擁有定義;而局部變量只能在函數內有效。 
在函數體內,同名的局部變量或者參數的優先級會高於全局變量。也就是說,若是函數內存在和全局變量同名的局部變量或者參數,那麼全局變量將會被局部變量覆蓋。 
全部不使用var定義的變量都視爲全局變量.net

三、函數做用域和聲明提早

JavaScript的函數做用是指在函數內聲明的全部變量在函數體內始終是有定義的,也就是說變量在聲明以前已經可用,全部這特性稱爲聲明提早(hoisting),即JavaScript函數裏的全部聲明(只是聲明,但不涉及賦值)都被提早到函數體的頂部,而變量賦值操做留在原來的位置。以下面例子: 
註釋:聲明提早是在JavaScript引擎的預編譯時進行,是在代碼開始運行以前。code

var scope = 'global';
function f(){
    console.log(scope);
    var scope = 'local';
    console.log(scope);
}

因爲函數內聲明提高,因此上面的代碼其實是這樣的 blog

var scope = 'global';
function f(){
    var scope;    //變量聲明提高到函數頂部
    console.log(scope);
    scope = 'local';    //變量初始化依然保留在原來的位置
    console.log(scope);
}

 通過這樣變形以後,答案就就很是明顯了。因爲scope在第一個console.log(scope)語句以前就已經定義了,可是並無賦值,所以此時scope的指是undefined.第二個console.log(scope)語句以前,scope已經完成賦值爲’local’,因此輸出的結果是localip

函數聲明提高

一、函數的兩種建立方式

  • 函數聲明
  • 函數表達式

函數聲明語法內存

f('superman');
function f(name){
    console.log(name);
}

運行上面的程序,控制檯能打印出supemran。 
函數表達式語法作用域

f('superman');
var f= function(name){
    console.log(name);
}

運行上面的代碼,會報錯Uncaught ReferenceError: f is not defined(…),錯誤信息顯示說f沒有被定義。 
爲何一樣的代碼,函數聲明和函數表達式存在着差別呢? 
這是由於,函數聲明有一個很是重要的特徵:函數聲明提高,函數聲明語句將會被提高到外部腳本或者外部函數做用域的頂部(是否是跟變量提高很是相似)。正是由於這個特徵,因此能夠把函數聲明放在調用它的語句後面。以下面例子,最終的輸出結果應該是什麼?:get

var getName = function(){
    console.log(2);
}
function getName (){
    console.log(1);
}
getName();

可能會有人以爲最後輸出的結果是1。讓咱們來分析一下,這個例子涉及到了變量聲明提高函數聲明提高。正如前面說到的函數聲明提高,函數聲明function getName(){}的聲明會被提早到頂部。而函數表達式var getName = function(){}則表現出變量聲明提高。所以在這種狀況下,getName也是一個變量,所以這個變量的聲明也將提高到底部,而變量的賦值依然保留在原來的位置。所以上面的函數能夠轉換成下面的樣子:io

function getName(){    //函數聲明提高到頂部
    console.log(1);
}
var getName;    //變量聲明提高
getName = function(){    //變量賦值依然保留在原來的位置
    console.log(2);
}
getName();    // 最終輸出:2

因此最終的輸出結果是:2。在原來的例子中,函數聲明雖然是在函數表達式後面,但因爲函數聲明提高到頂部,所以後面getName又被函數表達式的賦值操做給覆蓋了,因此輸出2

相關文章
相關標籤/搜索