藏宝游

 找回密码
 立即注册
查看: 89|回复: 0

[其它] 浅谈JavaScript 声明提升

[复制链接]

 成长值: 550

  • TA的每日心情
    开心
    2024-3-24 02:35
  • 签到天数: 5 天

    [LV.2]圆转纯熟

    灌水成绩
    47583
    8
    247942
    主题
    帖子
    积分

    等级头衔

    ID : 2

    超级版主

    积分成就 威望 : 1
    贡献 : 0
    杰币 : 105175
    在线时间 : 165 小时
    注册时间 : 2022-1-8
    最后登录 : 2024-4-17

    荣誉勋章
    最佳新人热心会员大富翁龙年大吉
    发表于 2024-3-10 13:27:51 | 显示全部楼层 |阅读模式
    1 引例及基本原理
    在学习JavaScript声明提升之前,我们先看下面这个例子:
    1. console.log(a);var a=2;
    复制代码
    运行结果会是什么?你可能会有以下的猜测:
    1.报错ReferenceError: a is not defined;
    2.打印2;
    3.打印undefined。
    正确的结果是第三种,打印undefined。
    下面让我们来看看具体的原因。其实,对于var a=2;这条语句,JavaScript会将其视为两个声明:
      定义声明var a,会在编译阶段进行;赋值声明a=2,会留在原地等待执行阶段进行。
    而所谓的声明提升:就是JavaScript会把var变量声明和函数声明都会被提升到各自作用域的顶部,而赋值操作并不会被提升。
    因此,上面的例子实际是按照这样的流程来处理:
    1. var a;console.log(a);a=2;
    复制代码
    我们还需要知道,不仅仅是var变量声明会提升,函数声明同样也会提升,现在来看下面这个例子
    1. foo();function foo(){ console.log(a); var a=2;}
    复制代码
    这个例子的运行结果为:打印undefined。这段代码实际上会被理解为为下面的形式:
    1. function foo(){ var a; console.log(a); a=2;}foo();
    复制代码
    2 关于声明提升的常见问题
    2.1 函数表达式
    先看一个函数表达式的例子:
    1. console.log(foo);var foo=function(){}
    复制代码
    上面代码的运行结果为:打印undefined。实际上,变量标识符foo被提升了,但它的赋值操作并没有被提升,我们可以理解为下面的形式:
    1. var foo;console.log(foo);foo=function(){}
    复制代码
    结论:函数声明会被提升,但函数表达式不会被提升。
    2.2 声明的优先级

    如果在同一个作用域内,存在同名的函数声明和var变量声明,那么会发生什么样的情况呢?我们同样再来看一个例子:
    1. function a(){}var a;console.log(a);
    复制代码
    1. var a;function a(){}console.log(a);
    复制代码
    上面的两种写法,运行结果均为打印a(){}。也就是说,如果在同一个作用域内,存在同名的函数声明和var变量声明,则函数声明的优先级更高。
    还有一种情况:如果同一个作用域内,存在多个同名的函数声明。这种情况下,后面声明的会覆盖前面声明的。
    3 练习题
    3.1 第一题
    1. var getName = function() { console.log(1);}function getName() { console.log(2);}getName();
    复制代码
    答案:打印1
    解析:提升后的顺序如下
    1. var getName;//与函数声明同名,故失效function getName() { console.log(2);}getName = function() {//赋值 console.log(1);};getName();
    复制代码
    3.2 第二题
    1. var a = 1;function b(){ a = 10; return; function a(){  console.log(a); } }b();console.log(a);
    复制代码
    答案:打印1
    解析:首先,我们需要梳理清楚声明的提升。
    本题有几个关键点,我们需要明白:
    函数b内的a函数虽然在return之后,但它并没有失效,它会发生声明提升,从而提升到b函数作用域的顶部。
    很多童鞋(比如我TAT)可能会错误地认为这题的答案是10,认为我们在最后调用了b函数,修改了全局变量a。实际上,由于函数a发生了声明提升,导致在函数b内“遮蔽”了全局作用域中的变量a,因此,a=10;其实是将函数a重新赋值。为了进一步测验,大家可以把a函数注释掉,会发现此时的答案就变成了10。
    注:本题还涉及到了闭包的相关知识,这一题详细的解析请见参考资料[2],讲得非常详细。
    1. var a;//全局变量a发生了声明提升function b(){ function a(){//函数a发生声明提升   console.log(a);  } a = 10;//因为函数a离它最近,因此赋值给函数a return; }a = 1;//赋值给了全局变量ab();console.log(a);
    复制代码
    4 参考资料

    [1] 《你不知道的JavaScript》
    [2] js中变量名与函数名重名的问题,Charles_Tian
    [3] 函数声明与变量声明的提升机制优先级问题,一个菜鸟的奋斗史
    以上就是浅谈JavaScript 声明提升的详细内容,更多关于JavaScript 声明提升的资料请关注咔叽论坛其它相关文章!

    原文地址:https://www.jb51.net/article/195552.htm
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    小黑屋|手机版|Archiver|RSS|藏宝游 ( 豫ICP备2021017492号 )|网站地图

    GMT+8, 2024-4-29 14:23 , Processed in 0.033783 second(s), 10 queries , Redis On.

    Powered by Discuz! X3.4

    本站不储存任何资源,所有资源均来自用户分享的网盘链接。
    本站为非盈利性站点,不会收取任何费用,所有内容不作为商业行为。

    快速回复 返回顶部 返回列表