个性化阅读
专注于IT技术分析

JS闭包和闭包函数 – JavaScript高级教程

上一章JavaScript教程请查看:JS函数提升和变量提升

在本教程中,你将了解什么是JavaScript闭包以及它是如何工作的。

了解JavaScript闭包

在JavaScript函数一章中,你已经了解到,在JavaScript中,变量的作用域可以是全局的,也可以是局部的,在ES6中,你还可以使用let关键字创建块范围的变量。

全局变量可以在程序的任何地方访问和操作,而局部变量只能由它们声明的函数访问和操作。

但是,在某些情况下,你希望一个变量在整个脚本中都可用,但又不希望代码的任何部分都能够意外地更改其值。

让我们看看会发生什么,如果你试图实现这个使用全局变量:

// 全局变量
var counter  = 0;

// 一个专门用来操作'counter'变量的函数
function makeCounter() {
    return counter += 1;
}

// 调用函数
makeCounter();
console.log(counter); // : 1

makeCounter();
console.log(counter); // : 2

// 试图从外部操作'counter'变量
counter = 10;
console.log(counter); // : 10

正如你在上面的示例中所看到的,计数器变量的值可以在程序中的任何位置进行更改,而无需调用makeCounter()函数(第17行)。

现在,让我们尝试用局部变量实现同样的事情,看看会发生什么:

function makeCounter() {
    // 本地变量
    var counter  = 0;
	
    // 操作'counter'变量
    return counter += 1;
}

// 调用函数
console.log(makeCounter()); // : 1
console.log(makeCounter()); // : 1

在这种情况下,counter变量不能从外部操作,因为它是本地makeCounter()函数的变量,但是后续调用函数之后它的值也不会增加,因为每次我们调用这个函数重置计数器变量的值,你可以清楚地看到在上面的例子中(第11行)。JavaScript闭包可以解决我们的问题。

function makeCounter() {
    var counter = 0;
	
    // 内部函数
    function make() {
        counter += 1;
        return counter;
    }
    return make;
}

/* 执行makeCounter()函数并将返回的值存储在myCounter变量中 */
var myCounter = makeCounter();

console.log(myCounter()); // : 1
console.log(myCounter()); // : 2

在上面的例子中可以看到,内部函数make()是从外部函数makeCounter()返回的。因此,myCounter的值是内部的make()函数(第14行),调用myCounter可以有效地调用make()。在JavaScript中,函数可以赋值给变量,作为参数传递给其他函数,可以嵌套在其他函数中。

你还会注意到,内部函数make()仍然能够访问外部函数中定义的计数器变量的值,即使makeCounter()函数已经完成执行(第14行)。这是因为JavaScript表单闭包中的函数。闭包在内部存储对其外部变量的引用,并且可以访问和更新它们的值。

在上面的例子中,make()函数是一个闭包,它的代码引用外部变量计数器。这意味着无论何时调用make()函数,其中的代码都能够访问和更新计数器变量,因为它存储在闭包中。

最后,由于外部函数已经完成执行,所以代码的其他部分不能访问或操作计数器变量。只有内部函数可以独占访问它。

前面的例子也可以用匿名函数表达式来写,就像这样:

// 匿名函数表达式
var myCounter = (function() {
    var counter = 0;
	
    // 嵌套的匿名函数
    return function() {
        counter += 1;
        return counter;
    }
})();

console.log(myCounter()); // : 1
console.log(myCounter()); // : 2

提示:在JavaScript中,所有函数都可以访问全局作用域,以及它们上面的作用域。由于JavaScript支持嵌套函数,这通常意味着嵌套函数可以访问更高范围内声明的任何值,包括其父函数的范围。

注意:只要应用程序(即web页面)存在,全局变量就存在。然而,局部变量的生命周期很短,它们是在调用函数时创建的,在函数执行完后立即销毁。

创建Getter和Setter函数

在这里,我们将创建一个变量secret,并使用闭包保护它不被外部代码直接操作。我们还将创建getter和setter函数来获取和设置它的值。

此外,setter函数还将快速检查指定的值是否是数字,如果不是,则不会更改变量值。

var getValue, setValue;

// 自执行函数
(function() {
    var secret = 0;
    
    // Getter函数
    getValue = function() {
        return secret;
    };
    
    // Setter函数
    setValue = function(x) {
        if(typeof x === "number") {
            secret = x;
        }
    };
}());

// 调用函数
getValue(); // : 0
setValue(10);
getValue(); // : 10
setValue(null);
getValue(); // : 10

提示:自动执行的函数也称为立即调用的函数表达式(IIFE)、立即执行的函数或自动执行的匿名函数。

赞(0)
未经允许不得转载:srcmini » JS闭包和闭包函数 – JavaScript高级教程

评论 抢沙发

评论前必须登录!