菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
81
0

JavaScript闭包基础指南

原创
05/13 14:22
阅读数 1296

闭包是函数创建时范围内所有变量的集合。要使用闭包,请在另一个称为嵌套函数的函数内创建一个函数。内部函数将有权访问外部函数范围中的变量(Closure有助于访问外部函数范围),即使在返回外部函数之后也是如此。每次创建函数时都会创建闭包。

在继续了解闭包之前,让我们首先了解一下JavaScript作用域链。

通常,范围有两种:

  • 全局作用域

  • 局部作用域

在ES5版本中,函数内部的变量在外部不可见。但是,块内部的变量(条件如if或while)在外部也可见。

由此,ES5具有功能范围。没有块作用域。

根据ES5,使用函数是在代码中声明块作用域的唯一方法。

但是,在ES6中,通过提供块范围的let和const关键字可以缓解这种情况。

无论如何,最好了解JavaScript是如何逐步发展的。

让我们在ES5版本中继续:

var a = 10;
function app(){
   var b = 2;
   console.log(a); // 10
   console.log(b); // 2
}
console.log(b); //   ReferenceError: b is not defined
app();

我们已经知道,a是全局变量,b是特定于app函数的局部变量。

我们无法从局部范围中获取局部变量的值。

使用嵌套函数-函数内的函数

var a = 10;
function app(){
     var b = 2;
     var d = 3;
  function add(){
     var c = a + b;
   }
 return add;
}
var x = app();
console.dir(x);

在这里,app是父函数,add是子函数。

使用console.dir而不是使用console.log来控制指定JavaScript对象的所有属性,帮助开发人员获取该对象的属性

变量x被分配给app函数,而app函数返回add函数。 因此,我们可以看到add函数的所有对象属性。

如果在浏览器中看到控制台,则可以在Scopes数组中看到Closure对象。

1.jpg

由于内部函数添加访问外部函数变量b和d,所以这两个变量将被添加到闭包对象中以供引用。

让我们来看下一个闭包的例子:

var a = 10;
var startFunc;
function app(){
      var b = 2;
   function add(){
      var c = a + b;
      console.log(c);
   }
   startFunc = add();
}
app(); // Invoke the app function
startFunc; 
// as the app function invoked above will assign the add function to startFunc & console the value of c
  • 一个名为startFunc的全局函数被分配给add函数,add函数是父app函数的子函数。

  • 这只有在调用app函数之后才可能实现,否则startFunc将作为一个全局变量,没有任何赋值

闭包在JavaScript中的应用

我们大多数人在编码时使用闭包,但我们不知道为什么要使用闭包。JavaScript不像其他面向对象的编程语言那样具有私有公共受保护等访问修饰符。因此,我们必须使用函数来保护名称空间不受ES5中外部代码的使用。

特别是在函数中,立即调用的函数表达式(IIFE)是在声明之后立即执行的表达式。不需要在函数声明之后调用该函数。

IIFE允许用JavaScript编写模块模式(设计模式之一)。

IIFE的语法定义为:

(function(){
             //variables & scope that inside the function 
})();

让我们举个例子:

var studnetEnrollment = (function () {
    //private variables which no one can change
    //except the function declared below.
     var count = 0;
     var prefix = "S";
    // returning a named function expression
     function innerFunc() {
         count = count + 1;
         return prefix + count;
     };
 return innerFunc;
})();
var x = studnetEnrollment(); // S1
console.log(x);
var y = studnetEnrollment(); // S2 
console.log(y);

count和prefix是两个私有变量,不能被任何人改变,只能被内部函数访问(这里是它的innerFunc)。这种访问只能通过称为闭包(Closure)的特性实现。

  • 在第一次调用studentEnrollment函数时,函数中的count变量被innerFunc函数递增1。

  • 在第二次时,计数将递增计数的前一个值,即1到2

  • 这些都可以通过闭包特性实现。

结论

闭包是外部函数中的变量集合,它允许访问内部函数作用域来保护全局命名空间。

闭包使开发人员能够编写干净的代码,就像OOP语言一样,不会混淆ES5版本中的全局变量名和局部变量名。

快乐编码……! ! ! ! !

英文地址原文:https://www.freecodecamp.org/news/a-basic-guide-to-closures-in-javascript-9fc8b7e3463e/

发表评论

0/200
81 点赞
0 评论
收藏
为你推荐 换一批