执行上下文过程
1、预解析
参与预解析的参数包括
- 函数声明被提到最顶部
- 函数的所有形参
- 函数声明
- 如果有同名函数变量先后预解析,先有变量后有函数,函数覆盖变量
- 变量声明
- 如果有同名函数变量先后预解析,先有函数后有变量,函数不会被变量覆盖,还是维持函数声明
2、执行代码
function foo(a) {
var b = 2;
function c() {}
var d = function() {};
b = 3;
}
foo(1);
预解析foo函数内部作用域
a: 1,
b: undefined,
c: reference to function c(){},
d: undefined
执行后
a: 1,
b: 3,
c: reference to function c(){},
d: reference to FunctionExpression "d"
分析函数和变量重复声明被覆盖的案例
console.log(foo);
function foo(){
console.log("foo");
}
var foo = 1;
foo()
预解析
foo:funtion foo(){}//var foo无效
执行
console.log(foo);//foo(){}
window.foo=foo//foo(){}
window.foo=1
foo()//报错 1已经不是函数
分析函数和变量重复声明被覆盖的案例2
console.log(foo);
var foo = 1;
function foo(){
console.log("foo");
}
foo()
预解析
foo:1
-------------
foo:funtion foo(){}// foo(){}覆盖var foo=1
执行
console.log(foo);//foo(){}
window.foo=1
window.foo=foo//foo=1
foo()//报错 1已经不是函数
分析函数和变量重复声明被覆盖、块级作用域对函数声明的作用域影响
console.log(a);//undefind
var a = 0;
console.log(a);//0
if(true){
console.log(a);//f a(){}
a = 1
function a(){
};
a = 21;
console.log(a);//21
}
console.log(a);//1
预解析
a:undefined
{//块级作用域内
a:f a(){}
}
执行
console.log(a);//undefind
window.a = 0;
console.log(a);//0
{//块级作用域内
console.log(a);// f a(){}
a=1
window.a=a//1
a=21
console.log(a);//21-块级里的a
}
console.log(a);//1- window.a
分析函数和变量重复声明被覆盖、块级作用域对函数声明的作用域影响
函数声明会提升到全局已经所有块级作用域的顶部(其实就是会后面覆盖全局变量,代码没执行到f(),变量没定义仍然会是undefind)
var a //var 是声明
console.log(a);//undefined
if(true){
console.log(a);//块级作用域f a(){}预解析
function a(){//function和var 一样是声明
};
a = 21;//局部变量
console.log(a);//21
}
console.log(a);// f a(){}
预解析
a:undefined
{//块级作用域内
a:f a(){}
}
执行
window.a = undefind;
console.log(a);//undefined
{//块级作用域内
var a= f a(){}//f a(){} 类似var形成了局部变量同时提升到全局赋值给了window.a
console.log(a);// f a(){}
window.a=a// f a(){}
a=21
console.log(a);//21-块级里的a变成了局部变量
}
console.log(a);// f a(){}
再看一种情况
var a ;//var 是声明
console.log(a);//undefined
if(true){
console.log(a);//块级作用域f a(){}预解析
a=1
function a(){//function和var 一样是声明
};//window.a=1
a = 21;//局部变量
console.log(a);//21
}
console.log(a);//1
参考来自冴羽