闭包是函数创建时范围内所有变量的集合。要使用闭包,请在另一个称为嵌套函数的函数内创建一个函数。内部函数将有权访问外部函数范围中的变量(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对象。
由于内部函数添加访问外部函数变量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/
© 著作权归作者所有
发表评论