JS 变量提升

今天去面试了,总体感觉很不错,整个公司还有人的气氛都很棒,希望能顺利通过。

问到 JS 一些细节问题的时候发挥比较糟糕,有些是知道反应得太慢,有些是压根没接触过,还是积累的太少了。这篇的 JS 变量提升问题就是从没有接触过的,网上一搜一大把,实在是不应该。为了不给信息爆炸添砖加瓦。。。照例尝试就这个问题扯一些别的理解。


var foo = 1;
function bar() {
    if (!foo) {
        var foo = 10;
    }
    alert(foo);
}
bar();

运行结果为:10

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

运行结果为:1


此前有在资料上扫到过一眼,所以听到答案后第一时间反应过来是变量提升,但对变量提升的具体行为则不了解了。在蝴蝶书里有一笔带过提了一句“通常编写代码提倡把变量声明尽量贴近变量使用的位置,以提供上下文参考,但 Javascript 没有块级作用域,所以反而推荐在函数的顶部给出所有用到变量的声明。”(大意是这样,书没在手边,不确认了)

当时不太理解没有块级作用域为什么会影响这个,现在了解了变量提升就很容易理解了。


以上面第一段程序为例,其实它等价于:

var foo = 1;
function bar() {
    var foo;       // foo === undefined
    if (!foo) {    // !foo === true
        foo = 10;
    }
    alert(foo);    // alert(10)
}
bar();

可以看到,在 bar 函数内部的局部变量声明 var foo 被提升到了函数体的顶部,所以 !foo 成了 !undefined 结果为 true 。而后又被赋值 10 ,至于全局变量 foo 完全没参与进来。

虽然考点是变量提升,但个人认为,答出变量提升顶多合格分,这道题还有更实用的现实意义。


由于 !foo 所在的位置在提升前位于函数体第一行,而且 var fooif 语句的块内,增加了隐蔽性。即使开发者了解变量提升,如果看漏了下面的 var foo 很容易就会误认为是在使用全局的 foo 。只要函数体稍微复杂一点,这种事情就很容易发生了。

因此才会有前面蝴蝶书的那一段话,建议把函数内用到的所有变量的声明写在函数开头。

记得此前还听过一个类似的故事,一个 c 语言项目中隔三差五总会遇到在 if 里比较相等结果写成了赋值语句产生的 bug :

if (a=1) {
    ...
}

被这情况烦了多次之后,定下了这样一个要求,if 内的相等判断统一把常量写左边:

if (1=a) { // Error! 常量无法被赋值
    ...
}

这样一来,原来防不胜防的隐蔽 bug 变成了一个语法分析阶段就会暴露无遗的编译错误。

(当然,早有更加好的办法了,像上面中 if 括号内赋值的写法,在 lint 的过程中就会被提醒存在潜在问题,所以这里只是个例子。)


感觉工程上的许多规定真的很有趣,一个小小的限制,就能帮助你绕过许多的坑。不能光爬坑,爬完了还得给坑立个绕行路牌,这些积累下来的东西,才真正能体现出经验的价值吧。

希望自己也能尽快积累成一个靠谱的前端工程师 :-P


本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏程序员互动联盟

【入门指导】C和C++的区别

C和C++有啥区别,C直接干事情的,C++规划后直接干事情的。这个比喻不是很恰当,面向过程和面向对象,C就是每个细节都得一目了然,C++你把事情干出来了,我不管...

3084
来自专栏take time, save time

初级程序员面试不靠谱指南(一)

    “来到这英雄宴中的人物,就算本身武功不是甚高,见识也必广博,“太祖拳法”的精要所在,可说无人不知。乔峰一招打出,人人都是情不自禁的喝了一声采!这满堂大采...

3529
来自专栏编程

英语不好,能看懂编程吗?

学会编程不需要多高深的英语水平,想要学会编程,简单的英语水平足够了,现在的程序开发环境又很友好,基本上打开之后不需要怎么配置,直接写代码就行,程序语言无外乎顺序...

2110
来自专栏take time, save time

[细节决定B度]之二分搜索也不易啊

     实事求是的说二分搜索是我学习算法的时候学的最好,理解的最透彻,能够当时就写出代码的的算法。事到如今,就如我可以分分钟写出hello world一样,我...

3026
来自专栏Pythonista

day24,python习题

有两个列表,分别存放来老男孩报名学习linux和python课程的学生名字 linux=['钢弹','小壁虎','小虎比','alex','wupeiqi'...

1542
来自专栏中国白客联盟

35行代码实现千万级别字典的快速去重

字典对于一个安全从业者的意义非常重要,尤其是渗透测试工程师,一份好的字典往往能带来意外的收获。 在当前各种裤子满天飞的环境下,快速整理有用信息并加入自己的字典已...

5594
来自专栏诸葛青云的专栏

利用c语言制作简易计算器

学了c语言之后,总想着能用c语言能制作一些简单的小工具来。而利用c语言来制作一款简易的计算器是一个不错的选择,用这款计算器可以计算的加、减、乘、除。

6051
来自专栏前端说吧

JS-过滤敏感词【RegExp】

5106
来自专栏腾讯Bugly的专栏

iOS内存管理:从MRC到ARC实践

对于iOS程序员来说,内存管理是入门的必修课。引用计数、自动释放等概念,都是与C语言完全不同的。搞明白这些,代码才有可能不 crash。然而就是这么牛逼的内存管...

3575
来自专栏逸鹏说道

重温数据结构系列随笔:数据结构的基本概念

现在项目已经踏上正轨,有不少时间可以用来学习,昨晚发现柜子里那本大学时候啃过无数遍的(数据结构 C语言版),那真的无限感叹啊,初恋女友啊,大学回忆啊都涌上心头。...

2874

扫码关注云+社区

领取腾讯云代金券