zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

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

2023-03-15 22:05:04 时间

要弄清闭包产生的原因,首先要明白作用域链的概念。在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存在着父级作用域的引用,因此产生了闭包,形式变了,本质没有改变。