前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS 变量提升

JS 变量提升

作者头像
Alan Zhang
发布2018-10-19 14:53:55
7K0
发布2018-10-19 14:53:55
举报
文章被收录于专栏:Alan's Lab

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

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


代码语言:javascript
复制
var foo = 1;
function bar() {
    if (!foo) {
        var foo = 10;
    }
    alert(foo);
}
bar();

运行结果为:10

代码语言:javascript
复制
var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

运行结果为:1


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

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


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

代码语言: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 :

代码语言:javascript
复制
if (a=1) {
    ...
}

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

代码语言:javascript
复制
if (1=a) { // Error! 常量无法被赋值
    ...
}

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

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


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

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


本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档