我们先来看一道面试题,大家猜想一下,下面这段代码,打印出来的结果是什么

var name = 'World!';
(function () {
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();

这里打印出来的结果为什么是 Goodbye Jack, 而不是Hello World呢。

因为JS代码运行分为两个阶段:解析阶段和执行阶段

解析阶段:找到所有的声明,包括函数声明和var声明,并把声明操作提升到它所在执行环境的顶部(全局或者函数内),而赋值和逻辑操作则会被留在原地等待代码执行。

并且,当它发现了函数名与函数名或者函数名与变量名冲突的时候,处理原则是:‘处理函数声明冲突时会覆盖,处理变量声明时冲突会忽略’。(后面再详解)

经过解析阶段之后,我们的代码其实被解析成了这样:

var name = 'World!';
(function () {
var name; // 对变量name的声明会被提升到函数的顶部,并且局部的变量name会覆盖全局的变量name
if (typeof name === 'undefined') {
name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();

执行阶段:赋值和逻辑操作就会被放在执行阶段。所以当我们在执行阶段时,由于name变量的声明被提升了,在if内判断typeof name的时候,赋值操作(即name='Jack')还未执行,所以  typeof name === 'undefined'  判断结果为true,打印出来的结果就是‘GoodBye Jack’。

而在ES6中新规范中的 let,const 会不会执行变量提升呢? 我做了这么一个小实验

(function () {
console.log(i); // undefined
var i = 'test const';
})(); 
(function () {
console.log(i); // ReferenceError: i is not defined
let i = 0;
})();
  
(function () {
console.log(i); // ReferenceError: i is not defined
const i = 'test const';
})();

可以看到 let 和const 声明的变量是不会被提升的,这也是为什么一开始的时候我把字体标红:函数声明和var声明会被提升。

那我们接着说一下函数声明的提升

定义函数有两种非常常见的方式

function A(){   // 函数声明
alert('A');
} var B = function(){ // 函数表达式
alert('B')
}

对于用函数声明的方式定义的函数,我们可以在函数之前调用,这就是因为JS在解析阶段把整个函数提升到了全局环境的最上面,

而对于函数表达式方式定义的函数,我们在函数之前调用的话,会得到undefined的结果,因为var 声明的变量被提升了,但是赋值操作还没有执行

我们看一下执行结果

console.log(A); // ƒ A(){ alert('A'); }
function A(){
alert('A');
} console.log(B); // undefined
var B = function(){
alert('B')
}

  

关于js的解析和执行阶段的补充详解,将在下一篇博客中讲解

javaScript 变量提升 var let const,以及JS 的解析阶段和执行阶段的更多相关文章

  1. JavaScript变量声明var,let.const

    var声明变量的作用域限制在其声明位置的上下文中 var x = 0; // x是全局变量,并且赋值为0. console.log(typeof z); // undefined,因为z还不存在. f ...

  2. javascript变量提升详解

    js变量提升 对于大多数js开发者来说,变量提升可以说是一个非常常见的问题,但是可能很多人对其不是特别的了解.所以在此,我想来讲一讲. 先从一个简单的例子来入门: a = 2; var a; cons ...

  3. 回归基础: JavaScript 变量提升

    from me: javascript的变量声明具有hoisting机制,它是JavaScript一个基础的知识点,也是一个比较容易犯错的点,平时在开发中,大大小小的项目都会遇到. 它是JavaScr ...

  4. JavaScript变量提升 面试题

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  5. JavaScript变量提升和函数声明预解析

    1.首先理解函数作用域 在JavaScript中,变量的定义并不是以代码块作为作用域的,而是以函数作用作用域的.也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的.而如果该变量是 ...

  6. var 声明变量的变量提升问题(let/const)

    在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.既全局变量. <scrip ...

  7. js javascript变量提升

    var:变量提升(无论声明在何处,都会被提至其所在作用域的顶部) let:无变量提升(所在的块内,未到let声明时(即let声明之前),是无法访问该变量的(not defined)),let变量不能重 ...

  8. JavaScript: 变量提升和函数提升

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...

  9. javascript变量提升

    提升是一种将变量和函数的声明移到函数作用域(如果不在任何函数内的话就是全局作用域)最顶部的机制. 提升影响了变量的生命周期,一个变量的生命周期包含3个阶段: 声明——创建一个新变量,例如var myV ...

随机推荐

  1. JAVA I/O(六)多路复用IO

    在前边介绍Socket和ServerSocket连接交互的过程中,读写都是阻塞的.套接字写数据时,数据先写入操作系统的缓存中,形成TCP或UDP的负载,作为套接字传输到目标端,当缓存大小不足时,线程会 ...

  2. C#工程详解

    转:https://www.cnblogs.com/zhaoqingqing/p/5468072.html 前言 写这篇文章的目地是为了让更多的小伙伴对VS生成的工程有一个清晰的认识.在开发过程中,为 ...

  3. hdu Naive Operations 线段树

    题目大意 题目链接Naive Operations 题目大意: 区间加1(在a数组中) 区间求ai/bi的和 ai初值全部为0,bi给出,且为n的排列,多组数据(<=5),n,q<=1e5 ...

  4. JavaScript:正则表达式 分组2

    继续上一篇的写,这篇复杂点. 分组+范围 var reg=/([abcd]bc)/g; var str="abcd bbcd cbcd dbcd"; console.log(str ...

  5. Java-master(github)教材整理

    helloworld class HelloWorld { public static void main(String[] args) { System.out.println("hell ...

  6. HDU 2242 考研路茫茫——空调教室(边双连通分量+树形dp+重边标号)

    http://acm.hdu.edu.cn/showproblem.php?pid=2242 题意: 思路:首先求一下双连通分量,如果只有一个双连通分量,那么无论断哪根管子,图还是连通的. 最后只需要 ...

  7. POJ 1222 EXTENDED LIGHTS OUT(高斯消元解XOR方程组)

    http://poj.org/problem?id=1222 题意:现在有5*6的开关,1表示亮,0表示灭,按下一个开关后,它上下左右的灯泡会改变亮灭状态,要怎么按使得灯泡全部处于灭状态,输出方案,1 ...

  8. neu 1694 Primorial vs LCM 数论

    1694: Primorial vs LCM 时间限制: 4 Sec  内存限制: 128 MB[提交][状态][讨论版] 题目描述 Given N (2<=N<=10^14), what ...

  9. Cocos2d-x学习笔记(十二)3D特效

    特效类即是GridAction类,其实就是基于网格的3D动作类.需开启OpenGL的深度缓冲,否则容易3D失真. 下边是一个snippet,创建网格对象,并将其添加到当前layer:同时,将进行3D特 ...

  10. python 加密与解密

    加密算法分类 对称加密算法: 对称加密采用了对称密码编码技术,它的特点是文件加密和解密使用相同的密钥 发送方和接收方需要持有同一把密钥,发送消息和接收消息均使用该密钥. 相对于非对称加密,对称加密具有 ...