JavaScript之作用域和作用域链

一.什么是作用域

作用域即定义变量的区域,javascript 是不存在块级作用域的(例如 if 和 for 体现了没有块级作用域),javascript 除了全局作用域之外,只有函数可以创建的作用域。

// 例如:
if (true) {
  var name = "kebi";
}
console.log(name); //kebi  此时name是全局作用域,说明没有块级作用域

// ES6的出现 提供了两个定义变量的方式  let/const ,存在块级作用域
// 例如:
if (true) {
  const globalName = "kebi";
}
console.log(globalName); //直接报错 is not defined

注意:函数创建的作用域在函数定义时就已经确定了。而不是在函数调用时确定。(这是因为 js 采用的是词法作用域或者静态作用域)(这一点非常重要重要举一个例子)

// 例子一:
var name = "kebi";
function foo() {
  console.log(name);
}
function bar() {
  var name = "heyushuo";
  foo();
}
bar(); //这里打印的是  kebi
//在执行bar函数内部的foo()的时候,应为foo是在全局创建的,所以是在全局作用域,此时全局作用域中name=kebi,所以打印出来的是kebi
// 例子二:
var name = "kebi";
function bar() {
  var name = "heyushuo";
  function foo() {
    console.log(name);
  }
  foo();
}
bar(); //这里打印的是  heyushuo
//在执行bar函数内部的foo()的时候,应为foo是在bar作用域下创建的,所以是在bar作用域下,此时bar作用域中name=heyushuo,所以打印出来的是heyushuo

通过一张图片更清晰的看一下作用域

如上图,全局代码和 fn、bar 两个函数都会形成一个作用域。而且,作用域有上下级的关系,上下级关系的确定就看函数是在哪个作用域下创建的。例如,fn 作用域下创建了 bar 函数,那么“fn 作用域”就是“bar 作用域”的上级。 作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突

二.什么是用域链呢?

通过一个例子来看作用域链;

var name = "kebi";
var age = "36";

function foo() {
  var sex = "男";

  function bar() {
    console.log(name);
  }
  bar();
}

foo(); //执行这个方法
// bar()函数中打印的是什么呢?
// 1.先在bar作用域里查找变量name,不存在
// 2.接着要到创建这个函数的那个作用域中取值——是“创建”,即foo作用域内,发现还是没有
// 3.最后就是向全局作用域去寻找,发现name是kebi,结束,打印   出 kebi

// 这样一步一步的找,直到找到全局作用域为止,这个路线我们称之为作用域链

参考:

原文地址:https://www.cnblogs.com/heyushuo/p/9967640.html