js變量提升和函數提升
阿新 • • 發佈:2017-06-08
問題 發現 blog 賦值 func 當前 color html 根據
變量,作為編程語言最基礎的部分,每種語言的變量不盡相同,但又大徑相庭。大部分編程語言的變量有塊級作用域,如if、for、while... 但JavaScript不純在塊級作用域,而是函數作用域,並且有自己獨有的特性--變量提升。(ES6新添加的let、const使其可以用塊級作用域)
對於函數的變量訪問時遵循作用域鏈的,即當前函數運行時會有一個當前作用域,當飲用某個變量時,會先查找當前作用域內是否存在該變量的定義,如果不存在則根據作用域鏈向上去查找父函數的作用域,有則拿來使用,沒有則繼續向上直到全局作用域。關於作用域鏈這裏就不仔細描述,簡單而言,類似原型鏈,從全局函數直到當前函數的作用域存在一種相互包含的關系,子可以向上訪問,但是父不可以向下訪問子函數的變量,這樣層層嵌套的關系鏈。
作用鏈域如下:
var num = 10;
function a (){
console.log(num);
}
a() ; //結果alert(10),a函數作用域裏沒有num 所以向上查找外層的作用域,有且等於10所以彈出10而不是undefined.
變量的提升:
var num = 10;
function a (){
//var num;
console.log(num);
var num = 11; //num = 11;
}
a(); // undefined
這段代碼中,function a(){}裏的var num = 11; 就拆分等價於被註釋掉的藍色部分,這就是變量提升--所有的變量都事先被提升到所屬函數作用域的頭部聲明。
再來看看有關函數形參的問題,第一段代碼稍加改動:
var num = 10;
function a (num){
console.log(num);
}
a() ; //結果undefined,a函數作用域定義形參num,由於沒賦值,所以為undefined
函數的提升:
函數的聲明方式有倆種:函數聲明和函數表達式,在函數提升方面會有所不同
函數聲明的函數提升:
console.log(fn); //function fn(){console.log(1);}
function fn(){
console.log(1);
}
等同下面一段代碼:
function fn(){
console.log(1);
}
console.log(fn); //function fn(){console.log(1);}
函數聲明中,聲明的函數整體被提升到作用域最頂部。
函數表達式的函數提升:
console.log(fn); // undefined
var fn = function (){
console.log(1);
}
等同下面一段代碼:
var fn;
console.log(fn); // undefined
fn = function (){
console.log(1);
}
函數表達式中,類似於上面講的變量提升,var出來的變量被提到作用域最頂部聲明。
如有發現錯誤之處,歡迎拍磚指正,感激不盡!
最後附加一道經典面試題:http://www.codeceo.com/article/one-javascript-interview.html
js變量提升和函數提升