先說幾個概念:面試
一、js代碼從上往下執行 瀏覽器
二、變量提高:函數
變量提高是瀏覽器的一個功能,在運行js代碼以前,瀏覽器會給js一個全局做用域叫window,window分兩個模塊,一個叫內存模塊,一個叫運行模塊,內存模塊找到當前做用域下的全部帶var和function的關鍵字,執行模塊執行js代碼,從上到下執行,遇到變量就會經過內存地址去查找這個變量,有和沒有這個變量。有這個變量就會看賦值沒賦值,若是賦值就是後面的值,若是沒有賦值就是undefined,若是沒有找到就說這個變量 is not defined。spa
三、做用域鏈:blog
當函數內部的變量被使用時,首先會在本身的私有做用域下查找是否有這個變量,若是有就使用,若是沒有就會向上一級(父級)查找,父級有就使用父級的,若是沒有就繼續向上一級找,有就使用,沒有就接着往上找,直到window,window有就用,沒有就是is not defined。咱們管這種查找機制叫作做用域鏈。內存
1、簡單的小案例:作用域
一、io
var a = 12;console
function fn(){function
console.log(a); //undefined
var a = 45;
console.log(a); //45
}
二、
function fn(){
console.log(11);
function ff(){
console.log(22);
}
ff();
}
fn() //11
ff() // ff is not defined
三、
var a = 123;
function fun(){
alert(a) //123
}
fun(); //私有做用域下沒有聲明變量a,就在父級找,有就直接使用。
四、
var a = 123;
function fun(){
alert(a); //123 私有做用域裏並無聲明變量a,因此就在父級找,有就直接使用。
a = 456;
}
fun()
alert(a) //456 fun()裏改變了全局變量a的值
五、
var a = 123;
function fun(a){
alert(a); //undefined 這裏有形參,可是並無傳實參
a = 456; //給參數賦值
}
fun();
alert(a) //123 全局變量a
六、
var a = 123;
function fun(a){
alert(a); //123 這裏傳了固定的參數123
a = 456;
}
fun(123)
alert(a) //123
七、
var a = 12;
function fn(){
console.log(a) //undefined 代碼從上往下執行,內存模塊只定義,不賦值。
var a = 45;
console . log(a) //45
}
fn()
八、
function test(a,b){
console . log(b) //function b(){} function關鍵字,在內存模塊裏面聲明和定義同時進行
console . log(a) //1
c=0;
a=3;
b=2;
console . log(b); //2
function b(){ }
function d(){ }
console . log(b) //2
}
test(1)
九、
function test(a,b){
console . log(a) //function a(){} 覆蓋了實參
console . log(b) //undefined
var b=234;
console . log(b) //234
a=123;
console . log(a) //123
function a(){ }
var a;
b=234;
var b=function (){ }
console . log(a); //123
console . log(b) //function
}
test(1)
2、阿里面試:
var a = 100;
function testResult(){
var b = 2 * a;
var a = 200;
var c = a / 2;
alert(b);
alert(c);
}
3、自調用函數:
+function(){
console.log(a);
var a = 5;
function a(){}
console.log(a);
function b(){}
b = 6;
console.log(b);
var c = d = b;
}()
console.log(d);
console.log(c);
注:自調用函數沒有變量提高!