闭包思考题的理解

比较下面两段代码,试述两段代码的不同之处 

// A--------------------------
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();

// B---------------------------
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();

核心区别:A 直接“把结果拿出来”,B 则“把能拿结果的工具递出来”

 A 段代码B 段代码
checkscope 返回值 字符串 "local scope" 内部函数 f(一个函数对象)
外层执行上下文在函数返回后的状态 立即可被回收——没有任何外部引用再指向它 f 捕获,形成闭包;其词法环境在函数返回后仍然存活
调用方式 checkscope() 一次调用就拿到字符串 第一次 checkscope() 得到函数,再调用一次 () 才拿到字符串
可复用性 不能复用;每次想得到值都得重新跑一遍 checkscope() 可以复用;保存 var fn = checkscope();,之后多次 fn() 都能访问同一个 scope
典型用途 立即求值的普通函数 需要持久化私有状态、做工厂函数/模块封装时

 

A 段

function checkscope() {
  var scope = "local scope";
  function f() { return scope; }
  return f();        // **马上执行 f**,返回字符串
}
checkscope();         // => "local scope"
  1. 创建并执行 checkscope 的执行上下文。

  2. f() 立刻运行,读取同作用域链里最近的 scope(即 "local scope")。

  3. checkscope 返回这个字符串后结束;其执行上下文随即出栈并等待垃圾回收。

B 段

function checkscope() {
  var scope = "local scope";
  function f() { return scope; }
  return f;          // **返回函数本身**,不执行
}
checkscope()();       // => "local scope"
  1. 第一次调用 checkscope()

    • 创建执行上下文,声明 scopef

    • 返回函数对象 f,但 checkscope 的词法环境被 f 闭包引用,无法回收。

  2. 紧接着对返回的函数再调用一次 ()

    • 运行 f 时沿着保存的作用域链找到那份仍然存在的 scope,得到 "local scope"

const getter = checkscope();
console.log(getter());  // "local scope"
console.log(getter());  // 仍然是同一份 "local scope"

就能看出闭包让内部私有数据跨越了原本的生命周期。

 

总结一句话

  • A:只要立即用得到结果,闭包不会泄漏到外面。

  • B:把函数带着其私有数据“封装”出来,以后想用随时调用,典型闭包场景。

posted @ 2025-06-18 18:18  wuyongyu  阅读(4)  评论(0)    收藏  举报