Open jannahuang opened 2 years ago
闭包是 JavaScript 的一种语法特性。
闭包 = 函数 + 自由变量 对于一个函数来说,变量分为全局变量、局部变量(函数内部变量)和自由变量。 let count function add() { //访问了外部变量的函数 count += 1 } 将上面代码放在非全局环境里,就是闭包。(上例中,闭包是 count + add 组成的整体)。非全局环境可以用立即执行函数或者花括号(局部作用域)实现。 const add2 = function() { let count return function add() { count += 1 } }() 变量有全局变量和局部变量,由于 JavaScript 特殊的变量作用域,函数内部可以直接读取全局变量,而函数外部无法读取函数内部的局部变量。 要读取函数内部的局部变量,可以在函数内部再定义一个函数,这个新定义的函数可以读取到外层函数的变量。这时把函数 return 或者赋值给全局变量,就可以读取到函数内部的变量。 举例: function f1(){ var n=999; function f2(){ console.log(n); // 999 } return f2; }
闭包 = 函数 + 自由变量 对于一个函数来说,变量分为全局变量、局部变量(函数内部变量)和自由变量。
let count function add() { //访问了外部变量的函数 count += 1 }
将上面代码放在非全局环境里,就是闭包。(上例中,闭包是 count + add 组成的整体)。非全局环境可以用立即执行函数或者花括号(局部作用域)实现。
const add2 = function() { let count return function add() { count += 1 } }()
变量有全局变量和局部变量,由于 JavaScript 特殊的变量作用域,函数内部可以直接读取全局变量,而函数外部无法读取函数内部的局部变量。 要读取函数内部的局部变量,可以在函数内部再定义一个函数,这个新定义的函数可以读取到外层函数的变量。这时把函数 return 或者赋值给全局变量,就可以读取到函数内部的变量。 举例:
function f1(){ var n=999; function f2(){ console.log(n); // 999 } return f2; }
var result = f1(); result(); // 999
闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。可以理解为,能够读取其他函数内部变量的函数。 如果内部函数中引用了外部函数的变量,在这个内部函数被返回并在其他地方被使用后,它仍然引用着那个变量。这是因为内部函数的作用域链包含外部函数的作用域。 在调用一个函数时,会为这个函数调用创建一个执行上下文,并创建一个作用域链。然后用 arguments 和其他命名参数来初始化这个函数的活动对象。外部函数的活动对象是内部函数作用域链上的第二个对象。这个作用域链一直向外串起了所有包含函数的活动对象,直到全局执行上下文才终止。 在函数执行时,要从作用域链中查找变量,以便读、写值。 ```javascript function compare(value1, value2) { if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } let result = compare(5, 10);
函数执行时,每个执行上下文中都会有一个包含其中变量的对象。全局上下文中的叫变量对象,它会在代码执行期间始终存在。而函数局部上下文中的叫活动对象,只在函数执行期间存在。在定义compare()函数时,就会为它创建作用域链,预装载全局变量对象,并保存在内部的[[ Scope]]中。在调用这个函数时,会创建相应的执行上下文,然后通过复制函数的[[ Scope]]来创建其作用域链。接着会创建函数的活动对象(用作变量对象)并将其推入作用域链的前端。 作用域链其实是一个包含指针的列表,每个指针分别指向一个变量对象,但物理上并不会包含相应的对象。
闭包会保留它们包含函数的作用域,将使用闭包的函数设置为等于 null 会解除对函数的引用,从而让垃圾回收程序可以将内存释放掉。作用域链也会被销毁,除全局作用域之外的其他作用域也可以销毁。
在 JavaScript 中,每个运行的函数,代码块以及整个脚本,都有一个被称为词法环境(Lexical Environment)的内部关联对象。 词法环境对象由两部分组成:
一个“变量”只是环境记录这个特殊内部对象的一个属性。“获取或修改变量”意味着“获取或修改词法环境的一个属性”。
所有的函数在声明时都会记住创建它们的词法环境。所有函数都有名为 [[ Environment]] 的隐藏属性,该属性保存了对创建该函数的词法环境的引用。 [[ Environment]] 有对词法环境的引用。[[ Environment]] 引用在函数创建时被设置并永久保存。 当函数在查找变量时,首先搜索自己的词法环境,然后是外部的词法环境,并且在哪里找到就在哪里修改。 在变量所在的词法环境中更新变量。
以上笔记参考《现代 JavaScript 教程》,《JavaScript 高级程序设计》,JS 中的闭包是什么?,学习Javascript闭包(Closure)
闭包
闭包是 JavaScript 的一种语法特性。
var result = f1(); result(); // 999
函数执行时,每个执行上下文中都会有一个包含其中变量的对象。全局上下文中的叫变量对象,它会在代码执行期间始终存在。而函数局部上下文中的叫活动对象,只在函数执行期间存在。在定义compare()函数时,就会为它创建作用域链,预装载全局变量对象,并保存在内部的[[ Scope]]中。在调用这个函数时,会创建相应的执行上下文,然后通过复制函数的[[ Scope]]来创建其作用域链。接着会创建函数的活动对象(用作变量对象)并将其推入作用域链的前端。 作用域链其实是一个包含指针的列表,每个指针分别指向一个变量对象,但物理上并不会包含相应的对象。
闭包会保留它们包含函数的作用域,将使用闭包的函数设置为等于 null 会解除对函数的引用,从而让垃圾回收程序可以将内存释放掉。作用域链也会被销毁,除全局作用域之外的其他作用域也可以销毁。
延伸:词法环境
在 JavaScript 中,每个运行的函数,代码块以及整个脚本,都有一个被称为词法环境(Lexical Environment)的内部关联对象。 词法环境对象由两部分组成:
一个“变量”只是环境记录这个特殊内部对象的一个属性。“获取或修改变量”意味着“获取或修改词法环境的一个属性”。
所有的函数在声明时都会记住创建它们的词法环境。所有函数都有名为 [[ Environment]] 的隐藏属性,该属性保存了对创建该函数的词法环境的引用。 [[ Environment]] 有对词法环境的引用。[[ Environment]] 引用在函数创建时被设置并永久保存。 当函数在查找变量时,首先搜索自己的词法环境,然后是外部的词法环境,并且在哪里找到就在哪里修改。 在变量所在的词法环境中更新变量。
闭包的作用
以上笔记参考《现代 JavaScript 教程》,《JavaScript 高级程序设计》,JS 中的闭包是什么?,学习Javascript闭包(Closure)