深入解析变量声明提升和函数声明提升

web前端开发

共 1984字,需浏览 4分钟

 · 2021-02-24

来源 | https://segmentfault.com/a/1190000011326520

JS运行阶段

JavaScript的运行阶段分为预编译阶段和执行阶段,今天要讨论的变量声明提升和函数声明提升,就是在这个阶段完成的。
在预编译阶段,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'

总结:同名情况下,函数声明提升优先级要高于变量声明提升,且提升后该函数声明定义不会被提升后的同名变量声明所覆盖,但是会被后续顺序执行的同名变量赋值所覆盖。


本文完〜

浏览 14
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报