二、执行上下文与闭包
1. 由来
JavaScript中的闭包源于计算机科学中的一种理论概念,称为“λ演算”(Lambda Calculus)。λ演算是计算机科学的基础之一,1930年由Alonzo Church提出,它是一种用于描述计算过程的数学抽象模型,也是函数式编程语言的基础。
在JavaScript中,闭包是函数和声明该函数的词法环境的组合。这个环境包含了闭包创建时所能访问的所有局部变量。
理解闭包,需要理解JavaScript的特性和工作原理。JavaScript的函数在创建时,就确定了其操作的上下文环境,即词法作用域。这是因为JavaScript采用的是静态作用域,也叫词法作用域,函数的作用域在函数定义的时候就决定了。
例如:
function outer() { var name = 'JavaScript'; function inner() { console.log(name); } return inner;} var innerFunc = outer();innerFunc(); // 输出 'JavaScript'
在这个例子中,outer函数返回了inner函数。inner函数访问了outer函数的局部变量name,因此形成了一个闭包。即使outer函数执行完毕,name变量的引用仍然被保留,因此innerFunc在执行时仍然能够输出 'JavaScript'。
闭包的概念虽然来自计算机科学的深层理论,但在日常的JavaScript编程中,它是一个非常实用且常见的特性,被广泛用于如数据隐藏和封装、模块化编程、回调函数和计时器等许多场景中。
在JavaScript中,闭包是一个强大而复杂的特性,理解和利用好闭包对于编写高效且安全的代码至关重要。下面就让我们深入地了解一下JavaScript的闭包。
闭包是指那些能够访问自由变量的函数。什么是自由变量呢?如果一个变量在函数内部被引用,但它既不是函数的参数也不是函数的局部变量,那么就称之为“自由变量”。
例如,我们有一个外部函数和一个内部函数:
function outerFunction(outerVariable) { function innerFunction() { console.log(outerVariable); } return innerFunction;} var inner = outerFunction('Hello Closure');inner(); // 输出 'Hello Closure'
在这个例子中,outerFunction是一个外部函数,接受一个参数outerVariable。它包含一个内部函数innerFunction,这个内部函数没有自己的参数或局部变量,但却引用了外部函数的变量outerVariable。所以,我们说innerFunction是一个闭包,而outerVariable就是它的自由变量。
需要注意的是,由于JavaScript的垃圾回收机制,如果一个变量离开了它的作用域,那么这个变量就会被回收。但是,由于innerFunction是一个闭包,它引用了outerVariable,所以即使outerFunction执行完毕,outerVariable离开了它的作用域,但仍然不会被垃圾回收机制回收。
再者,每次调用外部函数,都会为内部的闭包创建一个新的作用域。例如:
var inner1 = outerFunction('Hello Closure 1'); var inner2 = outerFunction('Hello Closure 2'); inner1(); // 输出 'Hello Closure 1' inner2(); // 输出 'Hello Closure 2'
这里,inner1和inner2是两个不同的闭包。他们分别有自己的作用域,储存了不同的outerVariable。
带你读《现代Javascript高级教程》二、执行上下文与闭包(2)https://developer.aliyun.com/article/1349707?groupCode=tech_library