JavaScript中displayName();与return displayName的区别是什么?
嘿,这个问题问得特别好——刚好能帮你把闭包的核心特性挖得更透!我们结合这两段代码一步步拆解区别:
先看第一个代码示例:直接调用内部函数
function init() { var name = 'Mozilla'; function displayName() { alert(name); } displayName(); // 直接在父函数内部调用 } init();
这段逻辑里,init执行时会先创建局部变量name,再定义内部函数displayName,然后立刻调用displayName()。此时init的执行上下文还在JavaScript的调用栈里,name处于活跃状态,displayName作为内部函数自然能访问到它。
等displayName执行完弹窗,init也跟着执行完毕,它的整个作用域(包括name变量)就会被垃圾回收机制彻底清理掉——相当于“用完就扔”,没有留下任何持久的状态。
再看第二个代码示例:返回内部函数的引用
function makeFunc() { var name = 'Mozilla'; function displayName() { alert(name); } return displayName; // 返回内部函数本身,而不是调用它 } var myFunc = makeFunc(); myFunc();
这段的关键完全不同:makeFunc没有直接调用displayName,而是把displayName这个函数的引用返回了出去,赋值给了全局变量myFunc。
当makeFunc执行完毕后,它的执行上下文会被弹出调用栈,但因为myFunc还牢牢持有displayName的引用,而displayName又依赖makeFunc里的name,JavaScript的垃圾回收机制不会销毁name——这就是闭包最核心的价值:内部函数在父函数的作用域外部被调用时,依然能保留并访问父函数的局部变量。
核心区别总结
作用域生命周期不同:
- 直接调用
displayName():父函数执行完后,局部变量立刻被回收,没有留存。 - 返回
displayName:父函数执行完后,它的局部变量会被闭包“留住”,直到外部的引用(比如myFunc)被销毁才会被回收。
- 直接调用
函数的复用性不同:
- 直接调用的场景下,
displayName只能在父函数内部用一次,父函数结束后就不存在了。 - 返回函数的场景下,你可以在任何时候调用
myFunc(),甚至多次调用,每次都能访问到当初makeFunc里的name;如果多次调用makeFunc(),每个返回的函数还会持有自己独立的name变量。
- 直接调用的场景下,
闭包的价值体现不同:
第一个例子虽然符合闭包的基础定义(内部函数访问父作用域变量),但没有发挥闭包的真正作用——保存状态。第二个例子才是闭包的典型应用场景,比如创建私有变量、封装模块、实现函数柯里化等。
内容的提问来源于stack exchange,提问作者HKS
相关产品推荐
相关产品推荐

