之前一直觉会认为javascript代码执行是由上到下一行行执行的。自从看了《你不知道的JS》后发现这个观点并不完全正确。先来给大家举一个书本上的的例子:

  var a='hello world';
var a;
console.log(a);

一开始我觉得输出的是undefined。但是真正的结果是hello world。带着疑问再看另外一段代码:

console.log(a);
var a='hello world';
 

借鉴与上面的例子会认为会输出一个hello world,或者是抛出一个没有声明的异常错误,然而发现这两种想法也是错误。输出的结果是‘undefined’。这书非常人性化的总结出了结论是:

引擎解释javascript代码的之前会对其进行编译。在编译过程中会查找所有声明,并用合适作用域将他们关联起来。换句话说,在代码执行之前,会对作用域链中所有变量和函数声明先处理完先。所以,当遇到var a='hello world'中是 var a是先在编译阶段执行,然后在执行a='hello world'。所以,第一段代码实质上是:

var a;
a='hello world';
console.log(a);
 

所以输出的就就是helloworld。总结一句话就是:只有声明被提升,而赋值或其他运算会留在原地。所以第二段代码实际上就是:

var a;
console.log(a);
a='hello world';
 

介绍完这两个经典例子是时候来看看一下这个例子了:

var name = "world";
(function () {
if (typeof name == 'undefined') {
var name = 'yang';
console.log('Hello ' + name)
} else {
console.log('Hello ' + name)
}
})()

根据javascript的运行机制和javascript没有块作用域这个特点,可以得出,变量name会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的。所以上述代码就相当于:

var name = "world";
(function () {
var name;
if (typeof name == 'undefined') {
var name = 'yang';
console.log('Hello ' + name)
} else {
console.log('Hello ' + name)
}
})()
 

因此,if判断的时候typeof name == 'undefined'是true。所以会执行条件为true里面的代码。输出就是Hello yang。
那么如果想实现上面的函数,我们该如何实现?答案非常简单那就创建块作用域了。如何最简单的创建块作用域呢?那当然是采用es6的新特性let关键字。let关键字可以将变量绑定到所在的任意区域中通常在{...}中。换句话说。let为其声明变量隐性劫持到所在区域中。下列例子中:let就绑定到if (typeof name == 'undefined') {...}中。所以name不会被提升,所以判断就为假,于是就可以输出我们期待已久的‘helloworld’。

var name = "world";
(function () {
if (typeof name == 'undefined') {
let name = 'yang'; console.log('Hello ' + name)
} else {
console.log('Hello ' + name)
}
})()

注意点:let所在的块级作用域,在声明代码被运行前,是不会像var那样会被查找到,提前声明,而是运行到了该代码才会被声明执行。下面例子很好说明这个问题:

 
(function (){
console.log(b);
let b=2;
})()

详解js变量声明提升的更多相关文章

  1. 详解js变量、作用域及内存

    详解js变量.作用域及内存 来源:伯乐在线 作者:trigkit4       原文出处: trigkit4    基本类型值有:undefined,NUll,Boolean,Number和Strin ...

  2. 解读JavaScript中的Hoisting机制(js变量声明提升机制)

    hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ...

  3. js变量声明提升

    1.变量提升 根据javascript的运行机制和javascript没有块级作用域这个特点,可以得出,变量会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的. 变量声明提升至全局 ...

  4. Js 变量声明提升和函数声明提升

    Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...

  5. JS变量声明提升和函数声明提升

    JS代码在执行的时候会先找出执行代码中定义的变量和函数,对其进行声明. 例1:console.log(a); var a = 4; 此时输出undefined.a变量在执行console.log(a) ...

  6. JavaScript变量声明提升

    JavaScript代码在被解析引擎执行前,会被“编译”把变量声明等放在合适的作用域中,如果不了解这一点,会让人产生很多疑惑. 文章:详解js变量声明提升

  7. 变量声明提升 Vs. 函数声明提升

    1. 变量声明提升 先看以下代码: 1)var in_window = "a" in window; console.log(in_window); 2)var in_window ...

  8. [Effective JavaScript 笔记] 第12条:理解变量声明提升

    js支持词法作用域,即除了极少的例外,对变量的引用会被绑定到声明变量最近的作用域中. js不支持块级作用域,即变量定义的作用域并不是离其最近的封闭语句或代码块,而是包含它们的函数. 不了解这个会产生一 ...

  9. 详解js和jquery里的this关键字

    详解js和jquery里的this关键字 js中的this 我们要记住:this永远指向函数运行时所在的对象!而不是函数被创建时所在的对象.this对象是在运行时基于函数的执行环境绑定的,在全局环境中 ...

随机推荐

  1. 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV

    意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...

  2. java数组实现买彩票(重复则重新遍历查询思想)

    package com.wh.shuzu; import java.util.Arrays; /** * 买彩票 * @author 丁璐同学 * 重复则重新遍历查询思想 */ public clas ...

  3. C#中如何判断键盘按键和组合键

    好记性不如烂笔头子,现在记录下来,不一定会有很详尽的实例,只写最核心的部分. C# winform的窗体类有KeyPreview属性,可以接收窗体内控件的键盘事件注册.窗体和控件都有KeyDown,K ...

  4. Oracle本地动态 SQL

    本地动态 SQL 首先我们应该了解什么是动态 SQL,在 Oracle数据库开发 PL/SQL块中我们使用的 SQL 分为:静态 SQL语句和动态 SQL语句.所谓静态 SQL指在 PL/SQL块中使 ...

  5. 窗体WINFORM

    窗体的事件:删除事件:先将事件页面里面的挂好的事件删除,再删后台代码里面的事件 Panel是一个容器 1.Label -- 文本显示工具Text:显示的文字取值.赋值:lable1.Text 2.Te ...

  6. 构建一个.net的干货类库,以便于快速的开发 - 验证码

    一个验证码对于一个网站的作用不言而喻,而随着技术的发展验证码的种类也开始多了起来,发展至今很多网站已经不再使用一种验证码,为满足需求程序猿就要写很多的方法来适应需求,今天我就来介绍我之前收集到的验证码 ...

  7. java数据结构和算法04(链表)

    前面我们看了数组,栈和队列,大概就会这些数据结构有了一些基本的认识,首先回顾一下之前的东西: 在数组中,其实是分为有序数组和无序数组,我简单实现了无序数组,为什么呢?因为有序数组的实现就是将无序数组进 ...

  8. Java语法基础-final关键字

    final关键字主要用在三个地方:变量.方法.类. 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改: 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一 ...

  9. iOS-UI控件之UITableView(一)

    UITableView 介绍 UITableView 是用来用列表的形式显示数据的UI控件 举例 QQ好友列表 通讯录 iPhone设置列表 tableView 常见属性 // 设置每一行cell的高 ...

  10. Linux 时间同步 ntpdate

    ntpdate 使用网络计时协议(NTP)设置日期和时间.此命令仅应用于 AIX 4.2 或后期版本. 语法: ntpdate [ -b] [ -d] [ -s] [ -u] [ -aKeyid] [ ...