先说几个概念:面试
一、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);
注:自调用函数没有变量提高!