前言

大家好,今天我们来看一下js中的变量与函数提升相关知识点

为什么有变量提升

js和其他语言一样,都要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而不会改变其他语句的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二步则是在执行阶段执行到该语句的时候才执行。

相关题目与解析

先从一个简单的例子来入门:

a = 2;
var a;
console.log(a);
复制代码

你觉得以上的代码会输出什么?是输出undefined吗?如果是按照程序的自上而下执行的话,那么这一段代码确实是输出undefined,因为var a语句把a = 2的语句给覆盖了。然而,javascript并不是严格的自上而下执行的语言。

这一段代码的输出结果是2,是不是感到很意外?为什么会这样呢?这个问题的关键就在于变量提升(hoisting)。它会将当前作用域的所有变量的声明提升到程序的顶部,因此上面的代码其实等价于以下代码。这样是不是就很简单明了了。

var a;
a = 2;
console.log(a);
复制代码

那么接下来,我们再来看这个例子。

console.log(a);
var a = 2;
复制代码

你觉得以上的代码会输出什么?是直接报ReferenceError吗?还是输出2呢?

其实以上代码会输出undefined。为什么呢?我们之前说过,js会将变量的声明提升到顶部,可是赋值语句并不会提升。所以对于js来说,其实var a = 2是分为两步的:

1.var a;
2.a = 2;
复制代码

而js只会将第一步提升到顶部,所以上面的语句等价于:

var a;
console.log(a);
a = 2;
复制代码

js的变量声明其实大体上可以分为三种:var声明、letconst声明和函数声明

函数声明与其他声明一起出现的时候,就可能会引起一些困扰。我们来看下面的例子。

foo();
function foo() {console.log('foo');
}
var foo = 2;
复制代码

你觉得上面会输出什么?TypeError吗?还是输出foo呢?想一想再接着往下看。

当当当当,其实最后输出的结果是foo。这就引出了我们的问题了,当函数声明与其他声明一起出现的时候,是以谁为准呢?答案就是,函数声明高于一切!

那么,下面的例子呢?

foo();
function foo() {console.log('1');
}
function foo() {console.log('2');
}
复制代码

当出现多个函数声明,那怎么办呢?

上面这个代码输出结果为2。因为有多个函数声明的时候,是由最后面的函数声明来替代前面的。

想必经历了以上的例子,你应该已经对变量声明已经有一定的了解了。那么我再来出一道题目来测试下。

foo();
var foo = function() {console.log('foo');
}
复制代码

这道题目是不是非常简单啊?这道题和上面的第二道例子其实是一样的。var foo = function() {}这种格式我们叫做函数表达式

它其实也是分为两部分,一部分是var foo,而一部分是foo = function() {},参照例2,我们可以知道,这道题的结果应该是报了TypeError(因为foo声明但未赋值,因此fooundefined)。

上面我们提到了var声明,函数声明,那么接下来我们来讲讲letconst声明。

letconst其实也是有函数提升的概念,不过它们会比较特殊,与var不一样,它们存在一个临时(暂时)性死区的概念。我们可以通过一个例子来体现这一点。

var a = 2;
function test() {console.log(a);let a = 5;
}
test();
复制代码

你觉得上面的代码会输出什么呢?是输出2javascript,还是undefined呢?

如果说,let没有变量提升的效果的话,那么应该是输出2。如果说let拥有和var一样的变量提升效果的话,那么应该是输出undefined。然而,其实上面的代码是会报错的。会报"ReferenceError: a is not defined"错误。那么为什么呢?

这其实就是我说的,let虽然具有变量提升的功能,但是它又与var不一样,它具有一个临死性死区的概念。

临死性死区其实就是说,a我已经声明了,可是在没有到它赋值的时候,你都不能使用这个变量,不然就会报错。所以该当前作用域开始,一直到let a = 5为止这整一块,都是a变量的临死性死区,你不能使用它。

constlet它们的变量提升的效果是一样的,也都存在着临死性死区的概念。

总结

js会将变量的声明提升到js顶部执行。

因此对于这种语句:var a = 2;

其实上js会将其分为var a;a = 2;两部分,并且将var a这一步提升到顶部执行。

变量提升的本质其实是由于js引擎在编译的时候,就将所有的变量声明了,因此在执行的时候,所有的变量都已经完成声明。

当有多个同名变量声明的时候,函数声明会覆盖其他的声明。如果有多个函数声明,则是由最后的一个函数声明覆盖之前所有的声明。

letconst都具有变量提升的效果,但是它们都具有临死性死区,从作用域开始部分,一直到变量的声明语句这整一块,你都不能使用该变量。

大佬们如果发现了文中的错误,请在评论区指出,我会及时修正!

如果觉得对您有用请点个赞,谢谢大佬!

每日一题(开开森森学前端之变量与函数)相关推荐

  1. 面试准备每日五题:C++(一)——变量定义声明、#ifdef #else、结构体赋值、sizeof strlen、C和C++的static

    文章目录 1 变量的声明和定义有什么区别? 2 简述#ifdef.#else.#endif和#ifndef的作用 3 结构体可以直接赋值吗? 4 sizeof 和strlen 的区别 5 C 语言的关 ...

  2. 对数函数定义域和值域_呆哥数学每日一题 —— 复合函数值域

    如果想要获取往期每日一题电子版,可以加我微信:daigemath366,备注:知乎 每日一题 呆哥解析:这是一个函数和复合函数的综合问题 首先我们先把原函数的值域求出来 先直接求导: 导数不容易判断单 ...

  3. 学前端的后果原来这么严重?! | 每日趣闻

    戳一戳小程序查看更多! 往 期 趣 闻 ☞好听!前端竟然自己会变调!| 每日趣闻 ☞修完 Bug 后脑袋灵光一现 | 每日趣闻 ☞如果孩子想学编程,你会推荐哪个?| 每日趣闻 ☞那些令人羡慕的工位布置 ...

  4. dom更新到底在javascript事件循环的哪个阶段?「前端每日一题v22.11.17」

    dom更新到底在javascript事件循环的哪个阶段?「前端每日一题v22.11.17」 昨天写了一篇文章,是javascript的事件循环机制,然后在某乎上也发了,在发的时候看到了一个问题,dom ...

  5. 倪文迪陪你学蓝桥杯2021寒假每日一题:2.1日(2019省赛A组第10题)

    2021年寒假每日一题,2017~2019年的省赛真题.本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供.每日一题,关注蓝桥杯专栏: https://blog.csdn.net/w ...

  6. 新玩法来了,web前端教程公众号推出《每日一题》

    <每日一题>是一种新玩法,怎么玩?很简单. 直接回复 "我要做题" ,将获取最新一期的习题. 比如: 写下你认为正确的答案,回复给公众号. 还可以回复历史期号,查看历史 ...

  7. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.11日(2017省赛A第9题)

    2021年寒假每日一题,2017~2019年的省赛真题. 本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供. 后面的每日一题,每题发一个新博文,请大家看博客目录:https://b ...

  8. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.20日(2018省赛A组第8题)

    2021年寒假每日一题,2017~2019年的省赛真题. 本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供. 后面的每日一题,每题发一个新博文,请大家每天看博客蓝桥杯专栏: htt ...

  9. 倪文迪陪你学蓝桥杯2021寒假每日一题:1.19日(2018省赛A组第7题)

    2021年寒假每日一题,2017~2019年的省赛真题. 本文内容由倪文迪(华东理工大学计算机系软件192班)和罗勇军老师提供. 后面的每日一题,每题发一个新博文,请大家每天看博客蓝桥杯专栏: htt ...

最新文章

  1. Android EditText不弹出输入法焦点问题的总结
  2. 腾讯视频怎么设置下载视频位置
  3. 【OpenCV 例程200篇】41. 图像的灰度变换(灰度级分层)
  4. IP地址子网的划分机制
  5. 利用R与NumPy实现矩阵乘法
  6. 「CodePlus 2017 11 月赛」Yazid 的新生舞会(树状数组/线段树)
  7. JavaScript快速基础入门
  8. 围棋人机大战一周年:被AlphaGo改变的世界
  9. Java设计模式之观察者模式应用与实战
  10. linux上挂载iso文件,如何在Linux上挂载ISO文件
  11. Oracle配置本地网络服务名
  12. mac蓝牙连接有问题要怎么处理呢?
  13. IO缓冲(buffer)和高速缓存(cache)
  14. chrome浏览器自动填充时背景色改变(-webkit-autofill)
  15. 数据结构-图、二叉树、B(+)树
  16. 手机app和单片机蓝牙通讯c语言,单片机怎么和手机通信,你知道吗?
  17. Typo: In word 拼写检查
  18. 数字经济之新零售行动派:鸡毛换糖走向数智化
  19. VS Code 遇上 Java丨第二章:配置 Maven 构建工具
  20. 为什么加了@WebFilter注解,Spring却没有给我自动注入该过滤器?

热门文章

  1. 【LVS】负载均衡集群
  2. Oracle 11G RAC:生产环境下架构
  3. LoadRunner12使用教程(三)——Action迭代
  4. 自定义控件添加自定义属性问题
  5. .NET+IIS+MSSQL配置
  6. 玩转Regsvr32命令
  7. linux 调用栈打印
  8. 教你快速写出多线程Junit单元测试用例 - GroboUtils
  9. Linux非阻塞IO(八)使用epoll重新实现非阻塞的回射服务器
  10. 【UR #4】元旦三侠的游戏(博弈论+记忆化)