JavaScript的作用域和变量提升

  看了众多的书籍和文章后,决定自己来写一遍关于作用域的知识点来巩固一下。

作用域

  作用域在编程语言中,它是控制着变量与参数的可访问性和生命周期。

  作用域这个东西呢,可以假设它是一个采集工人,专注于收集和维护所有声明的标识符(变量),并且将标识符组成一系列的查询,并实现一套规则来管理标识符,确定执行环境(执行上下文)对标识符的使用权限。

function foo () {
  var a = 1, b = 3;
console.log(c) // 报错,变量c没有定义,父级函数不能获取子函数中的变量 // a => 1, b => 3
function bar () { var c = 5, d = 7; a += b + c; // 可访问父级函数的a,b变量,并修改变量a的值 } // a => 1, b => 3 bar();
// a => 9, b => } foo();

 

块级作用域

  在JS函数中的var声明,其作用域是函数体的全部,在ES6之前并没有块级作用域的说法,在ES5中只有全局作用域和函数作用域。

  大多数像C语言的语言都拥有块级作用域,就是在一个代码块中(在一对花括号中的语句)定义的所有变量在代码块的外部是不可访问的,定义在代码块中的变量会在代码块执行完毕后会释放掉。

  在ES6中的新特性:let、const提供了块级作用域。

if (true) {
  let a = 1;   
}
console.log(a)// Uncaught ReferenceError: a is not defined

变量提升(Hoisting)

  直觉上会认为JavaScript代码在执行时是由上到下一行一行执行的。但实际上并不完全正确,有一种特殊情况会导致这个假设是错误的。

  考虑下面的代码

a = 2;
var a;
console.log(a) // a => 2

  这种写法固然是不推荐的,但它却正确地输出出来,到底是为什么呢。

  再看看一下代码

console.log(a) // a => undefined
var a = 2

  搞明白这个问题,要了解引擎和编译器的机制。

  引擎在解释JavaSript代码之前首先会对其进行编译,编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来。

  因此,正确的思路是:在编译的时候,变量和函数在内的所有声明都会在任何代码被执行之前被处理。

  当然,用ES6中的let就不会出现这个问题了,科科~

  

原文地址:https://www.cnblogs.com/ChivanTam/p/7322698.html