了解了闭包的基本原理后,有一个疑问仍然困扰着我:
封闭函数在执行后或返回闭包函数后驻留在哪里?
我相信函数驻留在堆栈数据结构中,并且一旦函数完成其执行/返回任何值,就会被抛弃堆栈顶部。
但是在Closures中,内部函数仍然必须访问Enclosing函数的状态,怎么样?
function sayHello(name) {
var text = name + ' !!!'; // Local variable
return function(wish) { console.log(wish + ', ' +text); }
}
var say = sayHello('Bob');
say('Hey');
say('Hello');
一旦它返回一个函数,sayHello
出现在哪里,从函数堆栈框架中删除它?
答案 0 :(得分:1)
这是一篇非常好的文章。
https://dmitryfrank.com/articles/js_closures
范围链
当执行任何JavaScript代码时,它需要一些地方来存储其本地变量。让我们将这个地方称为范围对象(有些人将其称为LexicalEnvironment)。例如,当您调用某个函数,并且函数定义局部变量时,这些变量将保存在范围对象上。您可以将其视为常规JavaScript对象,但明显不同的是您无法直接引用整个对象。您只能修改其属性,但不能引用范围对象本身。
范围对象的这个概念与C或C ++非常不同,其中局部变量存储在堆栈中。在JavaScript中,范围对象在堆中分配(或者至少它们的行为类似),因此即使函数已经返回,它们也可能保持分配状态。稍后会详细介绍。
正如您所料,范围对象可能具有父级。当代码尝试访问某个变量时,解释器会查找当前作用域对象的属性。如果该属性不存在,则解释器将移动到父作用域对象,并在那里查找。依此类推,直到找到价值,或者没有更多的父母。让我们将这个范围对象序列称为范围链。
在范围链上解析变量的行为与原型继承非常相似,同样有一个值得注意的区别:如果您尝试访问常规对象的某些不存在的属性,并且原型链不包含这个属性,它不是一个错误:undefined是以静默方式返回的。但是,如果您尝试访问作用域链上的非现有属性(即访问非现有变量),则会发生ReferenceError。