函数声明 和 var声明的优先级
1.变量声明 提升:
console.log(typeof a); // undefined
var a = 1;
console.log(typeof a); // number
执行过程 相当于:
var a;
console.log(typeof a); // undefined
a = 1;
console.log(typeof a); // number
2.函数声明 提升:
函数声明 的提升是一个 整体提升的过程;
demo:
console.log(typeof a); // function
function a(){}
console.log(typeof a); // function
如上的demo,足可以证明,这一结论;假如不是整体提升,是类似于 var变量声明的提升的方式,应该会如 var变量声明的方式的输出方式相同, 先输出 undefined,再输出 function;
3.无所谓 函数声明优先 or 变量声明优先
那么,又来了个问题,既然 var声明 和 函数声明 都有提升机制,那么它俩的声明提升优先级是什么样子呢;
为了论证这个我在网上看了好多资料,也查了好多书籍,大家一直认为 函数声明提升 优先于 变量声明提升,但是我发现,大家的论据都不够充分;比如如下的一个论证:
a(); // 1
var a;
function a() {
console.log(1);
}
a = function() {
console.log(2);
}
a(); // 2
然后,也描述了它的执行过程,相当于:
解释 A:
function a(){
console.log(1);
}
var a; // 遇到没有赋值的同名声明,忽略,不做操作;相当于什么都没有做
a(); // 1
a = function(){
console.log(2);
}
a(); // 2
如果如上的操作的解释,也可以通过,可以论证出 “函数声明提升 优先于 变量声明提升”;但是,按如下的理解应该也是解释的通的啊:
解释 B:
// 注意 var a 和 function a声明都会在栈空间开辟存储空间,并且 是占用同一块name为 a的空间;
var a; // 此时 a 没有赋值, 是个空的栈空间值
function a(){ // 找到 name为a的栈空间,给它赋值 function(){console.log(1)}, 相当于覆盖
console.log(1);
}
a(); // 1
a = function(){
console.log(2);
}
a(); // 2
看到了吧,如上的 论述也是行的通的,但是论述出来的结果 是“变量声明提升 优先于 函数声明提升”;这就尴尬了。。。
其实呢,我仔细想了一下,其实 谁先声明提升的都无所谓,因为 “var a 和 function a声明都会在栈空间开辟存储空间,并且开辟的是同一块 name为 a的空间,也就是说它们用的是同一块空间”;
4.函数声明先赋值,变量声明执行到赋值语句才赋值
因为两种声明方式共同操作一块栈空间,所以,主要看是谁先赋值的,我们再看一个例子:
console.log(typeof a); // function
var a = 1;
function a(){}
console.log(typeof a); // number
这就看的出来了,通过上边的这个demo, 明显可以看出来,应该 函数声明先赋值的,它是在执行上下文的执行阶段一开始的时候就已经进行了赋值操作,所以 最开始 typeof a 可以得到 function;而,变量声明 是要执行到赋值语句的时候才进行的赋值,所以 最后 typeof a 得到是 number;
如果不是这样的话,我们不妨做下假设:
假设1:都是最早赋值,不管谁先赋值,结果如下:
/*
->var 声明;
->函数声明;
->var 赋值;
->函数赋值:
->console.log(typeof a); // function 或者 number
->console.log(typeof a); // function 或者 number
*/
结果如上,最后输出不是同是 function 就是同是 number, 不符合正确输出;
假设2:都是执行到赋值语句的时候才赋值,无论 两种声明 谁前谁后,结果如下:
/*
->var 声明;
->函数声明;
->console.log(typeof a); // undefined
->赋值操作:
->console.log(typeof a); // function 或者 number
*/
结果如上,第一个输出一定都是 undefined, 不符合正确输出;
假设3:通过 (1) 和 (2)的不通过,那么只剩下一种可能了,都是先声明,然后一个先赋值,一个到 执行语句的时候才赋值;也就推测出了我们的结论:"函数声明先赋值,变量声明直到赋值语句的时候才赋值";执行过程如下:
/*
-> a 声明;// 因为同用一个栈空间,所以无所谓谁先声明
-> 函数声明赋值
->console.log(typeof a); // function
->变量声明赋值:
->console.log(typeof a); // number
*/
符合正确输出的结果;所以结论成立;
其实 函数的整体提升方式就已经论证了这一点,无论是如 解释 A 函数提升优先 + 忽略未赋值的 var 声明, 还是如 解释 B变量声明提升优先 + 函数后声明覆盖var 声明,最后都是在同一个栈空间上进行的操作,并无所谓,重要的是谁先进行的赋值操作;还有就是如上的这种 变量声明和函数声明是同名的用法,尽量不要在正式开发中使用,很容易就出现难以排查的异常;
4.总结
*->1.函数声明 和 变量声明都有声明提升机制
*->2.函数声明 是整体提升的方式,来进行的声明提升;
*->3.函数声明 和 变量声明,无所谓谁优先于谁,都是在预编译阶段进行的;(根据第4点的总结,也可以理解为 函数声明优先于变量声明)
*->4.函数声明赋值 要早于 变量声明赋值
**->.函数声明赋值,是在执行上下文的开始阶段进行的;
**->.变量声明赋值,是在执行到赋值语句的时候进行的赋值;
原创:转载注明出处,谢谢 :)
本文来自博客园,作者:驸马爷,转载请注明原文链接:https://www.cnblogs.com/cnblogs-jcy/p/8926310.html