深入解析变量声明提升和函数声明提升
web前端开发
共 1984字,需浏览 4分钟
·
2021-02-24 12:03
![](https://filescdn.proginn.com/8b7df9cc159f065d4e56575c8d3f02e6/21b62496f3d5ca2a896cf77de8da56c1.webp)
JS运行阶段
变量定义 使用var关键字定义的变量,并未赋值的情况下,该变量的值是undefined 变量作用域 全局变量的作用域遍布全局 局部变量的作用域仅在于函数内部 函数内部的同名变量或参数其优先级高于全局同名变量
变量声明提升
var name = 'ryan';
function say(){
console.log(name); //输出:undefined
var name = 'zoe';
console.log(name); //输出:'zoe'
}
say();
解析:上述代码从结果看,say函数执行第一次打印name时,并未打印全局的name('ryan'),而是打印局部的name(undefined),这是因为在预编译阶段,say函数内部进行了变量声明提升,提升后的执行效果如下:
var name = 'ryan';
function say(){
var name; //变量name声明提升至作用域顶部,但未赋值,故为undefined
console.log(name); //存在局部name,则无视全局name
name = 'zoe'; //变量赋值保持原位
console.log(name); //输出:'zoe'
}
say();
函数声明提升
函数的两种创建方式:
函数声明
函数表达式
函数声明:
say(); //输出:'saying'
function say(){
console.log('saying');
}
函数表达式:
say(); //报错:say is not a function
var say = function(){
console.log('saying');
}
解析:同样地先执行函数,后创建函数,结果却是不一样。原因在于,通过函数声明的方式,该函数声明(包括定义)会被提升至作用域的顶部,而表达式的创建方式则只提升了变量say至作用域的顶部,此时的say其值为undefined,调用say()自然报错“say不是一个方法”。
再来看一个示例:
var say = function(){
console.log('1');
};
function say(){
console.log('2');
};
say(); //输出:'1'
解析:预编译阶段进行变量声明提升和函数声明提升后,上述代码执行效果等同于:
var say; //变量声明提升
function say(){ //函数声明提升
console.log('2');
}
say = function(){ //变量赋值保持原位执行,say函数被覆盖
console.log('1');
};
say(); //输出'1'
总结:函数声明提升,会将函数的声明和定义全都提升至作用域顶部。
变量声明提升,只提升声明部分(未赋值状态),赋值部分保持原位置不动。
变量声明和函数声明提升的优先级
函数声明提升的优先级要高于变量声明提升。
先看一个简单示例:
console.log(say); //输出:[Function: say]
function say(){
console.log('1');
};
var say = '2';
console.log(say); //输出'2'
解析:本例中声明的函数和变量同名都是say,且函数声明在先,变量声明在后,按理说第一次打印say值预期会是undefined,然而结果是[Function: say]。
预编译阶段进行变量声明提升和函数声明提升后,上述代码执行效果等同于:
var say = function (){ //函数声明(包括定义)提升
console.log('1');
};
var say; //只是声明,并不会覆盖say的值
console.log(say); //故输出:[Function: say]
say = '2'; //此时say会被覆盖
console.log(say); //输出'2'
总结:同名情况下,函数声明提升优先级要高于变量声明提升,且提升后该函数声明定义不会被提升后的同名变量声明所覆盖,但是会被后续顺序执行的同名变量赋值所覆盖。
![](https://filescdn.proginn.com/3ed4c7b3a654d2713a55958ef0945093/5e17c02cc0de6193575bf45b38b83d6a.webp)
评论