前端面试 JavaScript— 闭包产生的原因?

Posted aiguangyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了前端面试 JavaScript— 闭包产生的原因?相关的知识,希望对你有一定的参考价值。

要弄清闭包产生的原因,首先要明白作用域链的概念。在ES5中只存在两种作用域:全局作用域和函数作用域,当访问一个变量时,解释器会首先在当前作用域查找标示符,如果没有找到,就去父作用域找,直到找到该变量的标示符或者不在父作用域中,这就是作用域链。值得注意的是,每一个子函数都会拷贝上级的作用域,形成一个作用域的链条。

比如:

var a = 1;
function f1() {
  var a = 2;
  return function f2() {
    console.log(a);
    // 2
  }
};

var num = f1();
num();

在这段代码中,f1 的作用域指向有全局作用域 (window) 和它本身,而 f2 的作用域指向全局作用域 (window)、f1 和它本身。而且作用域是从最底层向上找,直到找到全局作用域window为止,如果全局还没有的话就会报错。

这里 num 会拿到父级作用域中的变量,输出2。因为在当前环境中,含有对函数 f2 的引用,f2 恰恰引用了window、f1和f2的作用域,因此f2可以访问到f1的作用域的变量。

闭包产生的本质就是,当前环境中存在指向父级作用域的引用。

那是不是只有返回函数才算是产生了闭包呢?

回到闭包的本质,我们只需要让父级作用域的引用存在即可,因此我们还可以这么做:

var f2;
function f1(){
  var a=2
  f2 = function(){
    console.log(a);  
    // 2
  }
};
f1();
f2();

让f1执行,给f2赋值后,等于说现在f2拥有了window、f1和f2本身这几个作用域的访问权限,还是自底向上查找,最近是在f1中找到了a,因此输出2。

在这里是外面的变量f2存在着父级作用域的引用,因此产生了闭包,形式变了,本质没有改变。

以上是关于前端面试 JavaScript— 闭包产生的原因?的主要内容,如果未能解决你的问题,请参考以下文章

前端面试 JavaScript— 闭包有哪些表现形式?

前端面试 JavaScript— 闭包有哪些表现形式?

闭包 —JavaScript面向对象高级

对JavaScript中闭包的理解

前端JavaScript基础面试题01_JS基础知识(中)作用域闭包

JavaScript闭包(必考三座大山之二)