关于作用域链

JavaScript 有两种作用域:全局作用域和函数作用域。

var n = 1;

function f1() {
  console.log(n);
}
f1() // 1

函数内部可以直接读取全局变量,但是函数外部不能读取函数内部声明的变量。

function f1() {
  var n = 1;
}

console.log(n)
// Uncaught ReferenceError: n is not defined

如果出于种种原因,需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。

function f1() {
  var n = 1;
  function f2() {
  console.log(n); // 1
  }
}

JavaScript 语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。父对象的所有变量,对子对象都是可见的,反之则不成立。因此对于上述例子中,f2可以使用f1作用域中的变量。

function f1() {
  var n = 1;
  function f2() {
    console.log(n);
  }
  return f2;
}

var result = f1();
result(); // 1

闭包就是函数f2,即能够读取其他函数内部变量的函数。

由于在 JavaScript 语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。

闭包最大的特点,就是它可以“记住”诞生的环境,比如f2记住了它诞生的环境f1,所以从f2可以得到f1的内部变量。

在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

关于作用域链,只要记住先从自己的作用域下找,找不到从上层作用域找就可以了。

题1

var a = 1
function fn1(){
  function fn2(){
    console.log(a)
  }
  function fn3(){
    var a = 4
    fn2()
  }
  var a = 2
  return fn3
}
var fn = fn1()
fn() // 找出输出函数是 fn2,但是其作用域下无 a 的声明,再找上一级 fn1,a=2
题2

var a = 1
function fn1(){
  function fn3(){
    var a = 4
    fn2()
  }
  var a = 2
  return fn3
}
function fn2(){
  console.log(a)
}
var fn = fn1()
fn() // fn2 里没有,全局 a=1
题3

var a = 1
function fn1(){

  function fn3(){
    function fn2(){
      console.log(a)
    }
    var a

    fn2()
    a = 4
  }
  var a = 2
  return fn3
}
var fn = fn1()
fn() // fn2 没有,fn3 有,但是根据声明顺序,最终结果是 undefined

参考:http://javascript.ruanyifeng.com/ 、饥人谷

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 9,738评论 0 13
  • js的作用域链是由当前执行环境下的变量对象以及上层的执行环境下的变量对象组成,它保证了当前执行环境对符合访问它的权...
    a4316976150e阅读 2,695评论 0 0
  • 函数是一段可以反复调用的代码块。函数还能接受输入的参数,不同的参数会返回不同的值。 概述 函数的声明 JavaSc...
    许先生__阅读 3,251评论 0 1
  • 1 概述 1.1函数的声明 JavaScript 有三种声明函数的方法。 (1)function 命令 funct...
    徵羽kid阅读 3,047评论 0 1
  • 越是确定的东西越是没啥写的
    wxnwriting阅读 606评论 0 0

友情链接更多精彩内容