之前一直觉会认为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;
})()

最新文章

  1. Windows下nginx+php配置
  2. 第三篇 Replication:事务复制-发布服务器
  3. 移植mysql到嵌入式ARM平台
  4. linux vi查找命令
  5. HDOJ(HDU) 2162 Add ‘em(求和)
  6. LINQ to SQLite完美解决方案
  7. 基于visual Studio2013解决C语言竞赛题之0901文件读写
  8. 推广技巧:新站要如何推广引流做到日IP10000?
  9. 对象转字典 iOS
  10. org.hibernate.exception.ConstraintViolationException
  11. jmeter常见问题汇总
  12. Beautiful Soup 解析html表格
  13. centos6.5下安装tomcat
  14. 单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。
  15. 【learning】vim爆改记 (如何让vim用起来像devc++)
  16. QComboBox 树形视图选择
  17. Scrum立会报告+燃尽图(十一月二十三日总第三十一次):界面修改及新页面添加
  18. iOS socket Stream 服务器端 及 客户端 演示
  19. OKR学习总结
  20. http一些常见知识记录

热门文章

  1. 51nod 1096 距离之和最小
  2. 题解报告:hdu1202The calculation of GPA(算绩点问题)
  3. 持有对方的引用&&内部类
  4. Polynomial Division 数学题
  5. [转]Asp.net Mvc2中重构View的三种方式
  6. spark源码编译,运行example遇到:NoClassDefFoundError: org/spark_project/guava/cache/CacheLoader
  7. spring 中文乱码问题
  8. 黑马程序员----java基础:多线程
  9. 提高SQL查询效率 的10大方法
  10. Day3 CSS 引入及基本选择器