参考文章
面试题:四处分别输出什么?为什么?
console.log(a)//?
a();//?
var a =3;
function a(){
console.log(10);
}
console.log(a);//?
a = 6;
a();//?
正确代码顺序可以改为:
function a(){
console.log(10);
}
var a;//再次声明a,并未修改a的值,忽略此处声明
console.log(a)//输出函数本体
a();//函数声明提前,可调用,输出10
a =3;//这里修改值了,a=3,函数已不存在
console.log(a);//输出3
a = 6;//再次修改为6,函数已不存在
a();//a已经为6,没有函数所以没法调用,直接报错
变量声明提前(注意:赋值原地不变)
在函数体内声明一个变量,那么----在声明此变量的前后,你都可以直接使用它,并不会报错(注意:输出undefined表明未定义,但不会报错)
即:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内始终可见
这是因为声明统一提前,赋值原地不变------搞清楚什么是声明,什么是赋值
(function(){
console.log(a);//undefined
var a ="小钻风";
console.log(a);//小钻风
}())
等同于
(function(){
var a;//变量声明提前(赋值并没有提前)
console.log(a);//声明了但未赋值,所以输出undefined;
a ="小钻风";//赋值原地不变,即还在原来的位置赋值
console.log(a);//上一步赋值了,所以输出小钻风
}())
所以说变量a在function每一处都是可用的、
函数声明提前
只有函数声明格式的函数才会存在函数声明提前,比如函数表达式,构造函数,都不存在函数声明提前。
函数声明提前和变量声明提前类似
函数声明三种形式
- 函数声明: function name(x) {console.log(x)}
- 函数表达式: var name=function(x){console.log(x)}
- 构造函数: var name=new Function(‘x’,console.log(x)
函数声明提前,变量声明也提前,到底谁会更提的更前?
console.log(a);
var a = "孙悟空";
function a(){ console.log("小钻风"); }
函数会首先被提前,然后才是变量(仍然遵循声明统一提前,赋值原地不变的原则)
等同于
function a(){
console.log("小钻风");
}
var a;//由于上面函数已声明a,相同的变量名声明会被直接忽略
console.log(a);//输出函数本体
a = "孙悟空";
补充一段代码,加深理解
function getValue(condition) {
//var value; // 实际执行时(JavaScript 预编译阶段) var 声明提升到函数作用域顶部
if (condition) {
// value = "blue"; // 实际执行时,初始化动作还是留在了这里
var value = "blue";
return value;
} else {
// console.log(value); // undefined ,这里还是可以访问到 value 的,值为 undefined
return null
}
}