前端面试官最爱:闭包

284 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

此问题也是考察基础理解。很多人懂,但说起来一紧张就卡了。

问题顺序:

  1. 讲一下作用域?
  2. 谈谈对闭包的理解?
  3. 可以举个例子吗?
  4. 闭包的作用?

问答

Q:讲一下作用域?

A:作用域就是可访问变量,对象,函数的集合。变量如果在函数内声明,就是局部作用域,只能在函数内部访问。如果在函数外定义,就是全局变量。全局变量有全局作用域,在网页的所有脚本和函数中都可以用。

Q:ok,谈谈对闭包的理解?

A:MDN的解释是一个函数和对其周围状态的引用捆绑在一起,这样的组合是闭包。也就是说,闭包就是可以在一个内层函数中访问到其外层函数的作用域。在 JS 里,每创建一个函数,闭包就会在函数创建的同时被创建出来。

Q:可以举个例子吗?

A:假设在一个函数中定义一个函数,此时内部函数可以访问所有外部函数的局部变量,外层函数中定义一个局部变量a = 1,在内部函数中,return a; 因为在内部函数中,没有定义变量a,却可以使用,此时内部函数就是闭包函数。

Q:闭包的作用呢?

A:闭包最大的作用就是隐藏变量,闭包的有一个特性,内部函数总是可以访问在其所在的外部函数中声明的参数和变量,即使是在外部函数被返回之后。根据这个特性,JS可以实现私有变量,特权方法等。

聊到私有变量、特权方法,面试官可能会就这这个继续往下问,我这里就不多阐述了。

分析

作用域演示代码


var a = "test"; 

// 可调用 a 变量 
// 由于函数内没有声明b变量,所以函数外可调用b变量
function myFunction() { 
    // 函数内也可调用 a 变量 
    b = "xxx";
    // 可以调用 b 变量
}


闭包演示代码

function init() {
    var name = "Mozilla"; // name 是一个被 init 创建的局部变量
    function displayName() { // displayName() 是内部函数,这里就是一个闭包
        alert(name); // 使用了父函数中声明的变量
    }
    displayName();
}
var init1 = init();//此时已经形成了闭包,在很多语言中,一个函数的局部变量仅存与函数的执行期间,一旦init执行完毕,name就不能被访问了。但是这里依然可以正常运行,就是闭包的作用。
init1();