你知道下面的JavaScript代码执行时会输出什么吗?

var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
console.log(foo);
}
bar();

答案是“10”,吃惊吗?那么下面的可能会真的让你大吃一惊:

var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a);

答案是 “1”。为什么会这样呢,这就涉及到 JS 里面的作用域、作用域链和提升的相关知识了。

首先要明白 作用域和作用域链的内容(点击阅读),现在主要介绍提升。

在 JavaScript 中,当遇到 var a = 1; 这个语句时,我们可能会这么认为,“为一个变量分配内存,给这个变量命名为 a,再把 1 保存进去”。然而这个过程并不完全正确。当编译器遇到 var a = 1 时,会做以下两个步骤:

1. 遇到 var a ,首先会先看看当前的作用域中是否已经有 a,若有,就不再声明 a,若没有,就会在当前的作用域,创建一个 a

2. 然后处理 a = 1 。先查看当前作用域,是否有 a 。如果有,就把 1 赋值给 a 。如果没有,就向上一个作用域中寻找 a,直到寻找到全局作用域。全局作用域中如果还没有,就会抛出异常。

所以,当我们看到 var a = 1; 会认为这是一个声明,实际上这是两个声明, var a 和 a = 1 。第一个声明会在编译阶段进行,第二个声明会在原地等待执行。函数声明和变量声明总会被 JavaScript 的编译器提升到他们所在作用域的顶部。有了这些知识就可以解释上面的代码了

第一段代码实际上如下图:在遇到并执行 bar()函数时,执行到 if 语句里面的 foo,此时会先查询 bar()函数的作用域内有没有声明 foo:

若没有声明,就像上一个作用域中寻找 foo 有没有被声明。

若声明了,就直接将声明提升到 bar 作用域里的顶部(foo = 10 留在原地按顺序等待执行),这样,foo 就是 undefined,!foo 就是 true,可以进入 if 循环。

第二段代码实际上如下图:执行 b()时,首先就是 a = 10;这条语句,执行这条语句之前,先看 a 在 b 中是否被声明,若没有被声明就向上一个作用域中寻找 a ,现在的情况是,在 b 函数内部,a 以函数声明的方式,被声明了,那么就要把这个 a 函数声明提升到 a 所在的作用域的顶部,再按顺序执行后面的代码。

对于提升总结的知识点:

1. 函数声明和变量声明都会提升,但在同一个作用域相同名字的函数声明优先于变量声明。

2. 变量声明会提升,但变量赋值的过程不会提升,会在原地等待被执行。

3. 提升后,赋值语句会向前覆盖提升的内容。例子 2 中,b 函数的内部,最开始 a 是函数提升,a 的本质是函数,但是函数提升后,执行了一个赋值语句:a = 10;此时,a 就是一个 number 类型的变量了。

对于这种情况,我们在写 JavasScript 代码的时候该怎么做呢?

使用单 var 模式:避免变量提升所带来的问题

/*jslint onevar: true [...] */
function foo(a, b, c) {
var x = 1,
bar,
baz = "something";
}

本文参考以下资料:

颜海镜的博客:JavaScript作用域链和提升机制

你不知道的JavaScript

JavaScript高阶程序设计

JS 作用域与变量提升---JS 学习笔记(三)的更多相关文章

  1. JS作用域、变量提升和闭包

    作用域 作用域可以理解为JS引擎执行代码的时候,查找变量的规则. 从确定变量访问范围的阶段的角度,可以分为2类,词法作用域和动态作用域.js是词法作用域. 从变量查找的范围的角度,可以分为3类,全局作 ...

  2. js 作用域,变量提升

    先看下面一段代码: 代码执行的结果是: 1st alert : a = 0 2nd alert : a = undefined 5th alert : a = 0 3rd alert : a = 3 ...

  3. JS作用域和变量提升看这一篇就够了

    作用域是JS中一个很基础但是很重要的概念,面试中也经常出现,本文会详细深入的讲解这个概念及其他相关的概念,包括声明提升,块级作用域,作用域链及作用域链延长等问题. 什么是作用域 第一个问题就是我们要弄 ...

  4. js作用域和变量提升

    Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of ...

  5. JS 函数作用域及变量提升那些事!

    虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...

  6. JS _函数作用域及变量提升

    虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...

  7. 《Node.js开发实战详解》学习笔记

    <Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...

  8. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  9. javascript中的变量作用域以及变量提升详细介绍

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...

随机推荐

  1. python continue的应用

    count = 1sum = 0while count < 100: if count == 88: count += 1 continue if count % 2 == 0: sum = s ...

  2. VPS安全配置

    VPS安全配置 购买VPS后重装操作系统,以windows server 2008为例. 1 登录服务器 重装操作系统后,第一时间登录服务器,迅速进行安全配置. VPN-->Remote Des ...

  3. JavaScript 区分中英文字符的两种方法: 正则和charCodeAt()方法

    正则无疑是最强大的判断各种条件的方法, 最近也在研习它, 虽然枯燥, 但仍有乐趣. 用它来判断一个双字节的中文字符也是轻而易举地. 而判断中文字符,  简单且执行效率高. regExpForm.onb ...

  4. .htaccess实现php网站伪静态

    伪静态是啥?很简单,就是假的静态网页...例如有个网页是:www.xxx.com/index.php?id=1这是动态网页,php后缀的如果改成:www.xxx.com/index-1.html那么这 ...

  5. word_freq

    1) 博客开头给出自己的基本信息,格式建议如下: 学号:2017*****7193(保留前4位和后4位,中间用星号代替,避免泄露个人信息): 姓名:刘新飞,用你的真实姓名替代 我的码云仓库地址:[ht ...

  6. PHP----------php封装的一些简单实用的方法汇总

    1.xml转换成array,格式不对的xml则返回false function xml_parser($str){    $xml_parser = xml_parser_create();    i ...

  7. mysqlworkbench访问远程服务器

    1.如果服务器有防火墙,需要关一下: systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service # ...

  8. 微信网页授权获取用户openid及用户信息

    $code = $_GET["code"];//获取code $appid=“xxxx”;//公众号appid $APPSECRET="xxx";//公众号ap ...

  9. 2018-2019-2 网络对抗技术 20165335 Exp3 免杀原理与实践

    一.免杀原理与基础知识: (1)杀软是如何检测出恶意代码的? 检测特征码:特征码就是一般程序都不会有的代码,而后门有的那种特别的数据,而一个程序,应用有这种代码,数据的话,就直接判定为恶意代码. 主流 ...

  10. 软件综合实践Axure介绍

    首先就是下载安装Axure这款软件了,在百度上搜索“”Axure rp下载“”即可,下载完成后,打开exe安装,根据步骤一步步点击下一步即可完成安装. 运行该软件时会出现类似于填写激活码的东西,这时依 ...