题目重点:用计数器和循环回调解释闭包捕获绑定,避免把它当值的快照。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 讨论词法作用域;闭包保留可达绑定,不保证每次自动复制值。
解题路线
- 函数与其词法环境形成闭包,创建时决定能访问哪些外层绑定;调用地点不会随意改变词法变量来源。
- counter返回的函数读取并更新同一个count绑定;创建两次counter则产生不同环境,互不共享计数。
- var循环回调常共享同一绑定,let循环可有逐迭代绑定。异步执行发生在之后,不等于回调创建时把数字快照复制。
- 闭包可实现私有状态,但仍需考虑对象别名。长寿命监听器保留巨大对象可能造成可达内存积累,解除引用/订阅才可回收。
手动走一遍
makeCounter的两个实例各自从0增长;同实例调用两次得到1/2。把外层对象放进闭包后再修改字段,回调能看到修改,因为捕获绑定指向同对象。
规模与取舍
闭包数量与保留对象图影响内存,不只函数体大小;释放后是否立即GC不保证。热路径性能由引擎优化与访问方式决定。
易错点与追问
容易失分的边界
- 闭包捕获值的永久快照。
- 所有counter实例共享一个局部变量。
- 闭包天然泄漏无需找可达根。
继续深挖
- 如何解绑监听器释放状态?
- 模块私有状态与实例闭包怎么选?
技术参考
- MDN Closures:技术语义参考,具体题目按本文约定。
