美文网首页
Javascript闭包

Javascript闭包

作者: icestone2000 | 来源:发表于2019-05-20 10:44 被阅读0次

闭包是Javascript的一个基本概念,很多面试都会问到这一问题。如果到网上搜索可以找到很多对这个概念说明的文章。我看过很多这方面的文章,发现只有Mozilla的MDN上的这个文章讲得最为准确和简单。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

首先,我们来看看闭包的定义:

A closure is the combination of a function and the lexical environment within which that function was declared.

一个闭包是Javascript的函数和声明这个函数时它所包含的变量环境的组合。

这句话说得非常清楚,闭包是两个东西的结合体:其一是函数,其二是函数的词法环境(简单可以理解为变量环境)。

要了解闭包,首先我们要了解的是词法范围Lexical scoping(或者叫变量作用范围)。Javascript的语法和Java非常类似,但是在语法上最不相同的一点是变量的作用范围。在Java,C,C++中,函数体里只能访问全局变量或者函数内部定义的变量。在Javascript中,一个函数体里不光能访问全局变量,而且能访问外层函数里定义的变量,也就是说:一个变量在声明的函数体内可见,这个函数里的嵌入函数也能访问该变量。

请看下面的例子:

function init() {

    var name = "Mozilla"; // name is a local variable created by init

    function displayName() { // displayName() is the inner function, a closure

        alert (name); // displayName() uses variable declared in the parent function   

    }

    displayName();   

}

init();

嵌入函数displayName中能直接访问外层函数里定义的变量name。这一特性,直接导致了Javascript中必须有闭包的概念。也就是说Javascript的函数其实并不是自我封闭的,一个函数的运行结果与它外部函数中定义的变量也有关系。Java和C++等面向对象的语言其实也有类似的语法,一个对象的成员函数体里是能够访问对象的成员变量的,成员变量其实都是定义在成员函数外部,我们说到一个对象的成员函数,它其实包含了成员函数所在的对象环境。在Javascript中,为了表达这种函数与其外部环境的关系,所以引入了闭包的概念。

为了更加深入的理解闭包的概念,我们再来看下面的例子:

function makeFunc() {

  var name = 'Mozilla';

  function displayName() {

    alert(name);

  }

  return displayName;

}

var myFunc = makeFunc();

myFunc();

学过Java或者C++的人都知道,在一个方法内部定义的局部变量,在这个方法执行完后,局部变量的空间就会被释放,这个局部变量也就不再存在。但是在上面的例子中,makeFunc()这个函数执行完后,显然这个函数中定义的局部变量name还在继续存在,不然当myFunc()执行时会出错。

从这个例子我们可以看出,在Javascript里,当我们引用一个函数时,实际上被引用的函数外层的语法环境(也就是变量环境)实际上还是同时存在的,他们在一起构成了一个闭包。

我们可以利用闭包这一特性来实现一些有趣的功能。例如,在下面的例子中它通过闭包把函数和函数要处理的数据绑定在一起,生成了新的函数:

function makeSizer(size) {

  return function() {

    document.body.style.fontSize = size + 'px';

  };

}

var size12 = makeSizer(12);

var size14 = makeSizer(14);

var size16 = makeSizer(16);

另外我们要理解的是闭包的作用域链(Closure Scope Chain),这实际上也是理解Javascript里的变量作用域。我们知道闭包有三个作用域:

Local Scope (Own scope) 函数本身的作用域

    Outer Functions Scope 外层函数作用域

    Global Scope 全局作用域

其中要注意理解的是外层函数作用域。实际上,一个函数能访问它的所有外层函数中定义的变量,而不仅仅是它的直接外层函数。通过以下的例子我们就能了解,在最内层的函数实际上能访问所有外层函数定义的变量。

// global scope

var e = 10;

function sum(a){

  return function(b){

    return function(c){

      // outer functions scope

      return function(d){

        // local scope

        return a + b + c + d + e;

      }

    }

  }

}

console.log(sum(1)(2)(3)(4)); // log 20

关于闭包的性能考虑。从上面的说明我们知道,我们对一个函数的引用包含了函数的语法环境,即包含了该函数所引用的所有外层函数中的变量定义。所以我们在引用一个函数时,其可能占用的内存会很大,我们最好能避免。

相关文章

  • JavaScript----闭包

    javascript之闭包 闭包的概念     闭包(closure)是 JavaScript 的一种语法特性。 ...

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • javascript中闭包是什么

    javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量。私有变量可以用到闭包。闭包就...

  • Javascript 闭包

    闭包 (注:所以案例以 javascript 实现) 初识闭包 什么是闭包 MDNClosures are fun...

  • 作用域闭包

    概览 背景知识:JavaScript内存管理、JavaScript作用域。 内容 1 闭包定义 闭包:当函数可以记...

  • JavaScript 作用域

    概览 背景知识:JavaScript内存管理、JavaScript作用域。 内容 1 闭包定义 闭包:当函数可以记...

  • 20170815 前端开发日报

    JavaScript闭包,只学这篇就够了 闭包不是魔法 这篇文章使用一些简单的代码例子来解释JavaScript闭...

  • JavaScript深入理解-闭包(Closure)

    推荐文章:学习Javascript闭包(Closure)- 阮一峰javascript深入理解-从作用域链理解闭包...

  • 闭包

    学习Javascript闭包(Closure)

  • JS之闭包与IIFE

    本篇文章主要讨论了: JavaScript引擎 全局对象 闭包 循环 + 闭包 IIFE + 闭包 1.JavaS...

网友评论

      本文标题:Javascript闭包

      本文链接:https://www.haomeiwen.com/subject/vsdoaqtx.html