📜  JavaScript闭包

📅  最后修改于: 2020-09-27 04:14:41             🧑  作者: Mango

在本教程中,您将在示例的帮助下了解JavaScript闭包。

在学习闭包之前,您需要了解两个概念:

  • 嵌套函数
  • 返回函数

JavaScript嵌套函数

在JavaScript中,一个函数还可以包含另一个函数。这称为嵌套函数。例如,

// nested function example

// outer function
function greet(name) {

    // inner function
    function displayName() {
        console.log('Hi' + ' ' + name);
    }

    // calling inner function
    displayName();
}

// calling outer function
greet('John'); // Hi John

在上面的程序中, greet() 函数在其中包含displayName() 函数 。


返回函数

在JavaScript中,你也可以在函数中返回的函数 。例如,

function greet(name) {
    function displayName() {
        console.log('Hi' + ' ' + name);
    }

    // returning a function
    return displayName;
}

let g1 = greet('John');
console.log(g1); // returns the function definition
g1(); // calling the function

输出

function displayName() {
      console.log('Hi' + ' ' + name);
  }
Hi John

在上面的程序中, greet() 函数返回displayName 函数定义。

在此,将返回的函数定义分配给g1变量。使用console.log(g1)打印g1时 ,将获得函数定义。

要调用存储在g1变量中的函数 ,我们使用带括号的g1()


JavaScript闭包

在JavaScript中,封闭提供了从内部函数内部访问一个函数的外部范围,外部函数已经关闭后。例如,

// javascript closure example

// outer function
function greet() {

    // variable defined outside the inner function
    let name = 'John';

    // inner function
    function displayName() {

        // accessing name variable
        return 'Hi' + ' ' + name;
      
    }

    return displayName;
}

let g1 = greet();
console.log(g1); // returns the function definition
console.log(g1()); // returns the value

输出

function displayName() {
      // accessing name variable
      return 'Hi' + ' ' + name;
  }
Hi John

在上面的示例中,当调用greet() 函数 ,它返回displayName的函数定义。

在这里, g1是对displayName 函数的引用。

调用g1() ,它仍然可以访问greet() 函数。

当我们运行console.log(g1) ,它返回函数定义。

对于其他编程语言(例如Python,Swift,Ruby等),存在闭包的概念。

让我们看另一个例子。

// closure example

function calculate(x) {
    function multiply(y) {
        return x * y;
    }
    return multiply;
}

let multiply3 = calculate(3);
let multiply4 = calculate(4);

console.log(multiply3); // returns calculate function definition
console.log(multiply3()); // NaN

console.log(multiply3(6)); // 18
console.log(multiply4(2)); // 8

在上面的程序中, calculate() 函数使用单个参数x并返回multiply 函数的函数定义。 multiply() 函数采用单个参数y并返回x * y

multiply3multiply4都是闭包。

称为validate calculate() 函数传递参数x 。当multiply3multiply4被调用, multipy() 函数可以访问外部的传递参数x calculate() 函数。


资料私隐

JavaScript闭包有助于保护程序的数据私密性。例如,

let a = 0;
function sum() {
    function increaseSum() {

        // the value of a is increased by 1
        return a = a + 1;
    }
    return increaseSum;
}

let x = sum();
console.log(x()); // 1
console.log(x()); // 2
console.log(x()); // 3
a = a + 1;
console.log(a); // 4

在上面的例子中, sum() 函数返回的函数定义increaseSum 函数。

a变量在increaseSum() 函数increaseSum() 。但是, a变量的值也可以在函数外部更改。在这种情况下, a = a + 1;在函数外部更改变量的值。

现在,如果你想在一个变量中只在函数内部增加,你可以使用一个闭合。例如,

function sum() {
    let a = 0;
    function increaseSum() {

        // the value of a is increased by 1
        return a = a + 1;
    }
    return increaseSum;
}

let x = sum();
let a = 5;
console.log(x()); // 1
console.log(x()); // 2
console.log(a); // 5

在上面的例子中, sum() 函数设置0的值,并返回increaseSum 函数。

由于封锁,即使sum()已经执行, increaseSum()仍然有访问 ,并可以添加1 每次x()被调用。

并且a变量是sum() 函数的私有变量。这意味着a变量只能在sum() 函数内部访问。

即使你宣布a ,并使用它,它不会影响a中的变量中sum() 函数。

注意 :通常,闭包用于保护数据隐私。