javascript闭包_JavaScript的闭包和咖喱介绍

news/2024/7/17 9:21:47

javascript闭包

介绍 (Introduction)

If you write code in JavaScript it’s quite likely you have come across the term closure, which is a useful yet often confusing concept. But just what is a closure?

如果您使用JavaScript编写代码,很可能会遇到术语closure ,这是一个有用的但经常造成混淆​​的概念。 但是什么是闭包?

A closure may be described as a combination of a function and the lexical environment in which it was declared.

闭包可以描述为函数和声明它的词法环境的组合。

But what exactly does this mean? The lexical environment consists of any local variables in the function’s scope when the function is created. A closure enables one to refer to all local variables of a function in the state they were found.

但是,这到底是什么意思? 创建函数时, 词汇环境由函数范围内的所有局部变量组成。 通过闭包,可以在发现状态的情况下引用函数的所有局部变量。

This is essentially achieved by defining a function inside another function, this function within a function is technically the closure. Each time the parent function is called, a new context of execution is created holding a fresh copy of all local variables. These local variables can be referred to in the global scope by either linking them to variables declared globally or returning the closure from the parent function.

这基本上是通过在另一个函数内部定义一个函数来实现的,一个函数内的这个函数在技术上是闭包。 每次调用父函数时,都会创建一个新的执行上下文,其中包含所有局部变量的新副本。 通过将局部变量链接到全局声明的变量或从父函数返回闭包,可以在全局范围内引用这些局部变量。

A basic example will take on a format similar to this:

一个基本示例将采用类似于以下格式:

function closuredFunc (){
    function closure(){
    // some logic
    }
}

It is also possible to have a closure that returns several methods as shown below:

也可能有一个闭包,它返回几种方法,如下所示:

function closure(){
    function first() { console.log('I was declared first')}
    function second() { console.log('I was declared second')}
    function third() { console.log('I was declared third')}
    return [first, second, third]
}

To reference each of these methods, we’ll assign our closure to a global variable which will then point to an array of exposed methods. Each method can then be assigned to unique variable names to bring them into the global scope as shown below. At this point, they can now be called.

为了引用这些方法中的每一个,我们将闭包分配给一个全局变量,然后将其指向一组公开的方法。 然后,可以将每个方法分配给唯一的变量名称,以将它们带入全局范围,如下所示。 现在,可以调用它们了。

let f = closure()

let one = f[0]
let two = f[1]
let three = f[2]

one() // logs I was declared first
two() // logs I was declared second
three() // logs I was declared third

为什么要使用闭包? (Why Use Closures?)

You may be wondering why would one go through the trouble of making closures. Well, closures have a number of uses and advantages.

您可能想知道为什么有人会遇到关闭问题的麻烦。 好吧,封闭具有许多用途和优点。

Prior to the introduction of Classes in ES6, closures provided a means of creating class-like privacy similar to that used in Object Oriented Programming, allowing us to emulate private methods. This is known as the module pattern and it allows us to write easily maintainable code with reduced namespace pollution and more reusability.

在ES6中引入类之前,闭包提供了一种创建类似于类的隐私的方法,类似于面向对象编程中使用的方法,从而使我们可以模拟私有方法。 这称为module pattern ,它使我们能够编写易于维护的代码,从而减少名称空间污染并提高可重用性。

Let’s look at a case where this is done:

让我们看一个完成的情况:

var makeCounter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }
  return {
    increment: function() {
      changeBy(1);
    },
    decrement: function() {
      changeBy(-1);
    },
    value: function() {
      return privateCounter;
    }
  }
};

var counter1 = makeCounter();
var counter2 = makeCounter();

counter1.value(); // returns 0
counter1.increment(); // adds 1
counter1.increment(); // adds 1
counter1.value(); // returns 2
counter1.decrement(); //subtracts 1
counter1.value(); // returns 1
counter2.value(); // returns 0

In the above example, we have declared a function makeCounter which is a public function that has access to some private variables within it such as privateCounter and the functions that manipulate it. This mimics the behaviour of creating makeCounter as a class with it’s own built in fuctionality and variables. This can be seen when we create two different counters, counter1 and counter2. Each counter is independent to the other and references a different version of variables.

在上面的示例中,我们声明了一个函数makeCounter ,它是一个公共函数,可以访问其中的一些私有变量,例如privateCounter和对其进行操作的函数。 这模仿了将makeCounter创建为具有自己的功能和变量的类的行为。 当我们创建两个不同的计数器counter1counter2时,可以看到这一点。 每个计数器彼此独立,并引用不同版本的变量。

Closures also allow us to use functions to create other functions that add a specific value to their argument. In this case, the parent function allowing this behaviour is known as a function factory as it essentially creates other functions.

闭包还允许我们使用函数来创建其他函数,这些函数会为其参数添加特定的值。 在这种情况下,允许这种行为的父函数被称为function factory因为它实际上会创建其他函数。

Using function factories, we are able to achieve a behaviour known as Currying, which we’ll cover in the next section.

使用函数工厂,我们可以实现称为Currying的行为,我们将在下一部分中介绍。

什么是咖喱 (What is Currying)

Currying is the pattern of functions that immediately evaluate and return other functions. This is made possible by the fact that Javascript functions are expressions that can return other functions.

Currying是立即评估并返回其他功能的功能模式。 Javascript函数是可以返回其他函数的表达式,因此可以做到这一点。

Curried functions are constructed by chaining closures by defining and immediately returning their inner functions simultaneously.

通过链接闭包来构造Curried函数,方法是同时定义并立即返回其内部函数。

Here’s an example of currying:

这是currying的示例:

let greeting = function (a) {
    return function (b) {
        return a + ' ' + b
    }
}

let hello = greeting('Hello')
let morning = greeting('Good morning')

hello('Austin') // returns Hello Austin
hello('Roy') // returns Hello Roy
morning('Austin') // returns Good morning Austin
morning('Roy') //returns Good Morning Roy

The two functions created from greeting (hello and morning) each return functions that process the provided inputs to generate a greeting statement. They also take an argument which is the name of the person to be greeted.

greeting创建的两个函数( hellomorning )分别返回函数,这些函数处理提供的输入以生成问候语。 他们还接受了一个要打招呼的人的名字作为论点。

In the above case, greeting is also used as a function factory with the two functions hello and morning generated from it.

在上述情况下,greeting还用作函数工厂,并从中生成了两个函数hello和morning。

The inner function may also be called invoked after the first call as follows:

在第一次调用之后,也可以调用内部函数,如下所示:

greeting('Hello There')('General Kenobi') 
//returns Hello There General Kenobi

Currying is considered to be part of functional programming and as such curried functions may be easily written using the arrow function syntax in ES6 and newer versions of Javascript for cleaner, more elegant code:

咖喱被认为是函数式编程的一部分,因为咖喱函数可以使用ES6和较新版本的Javascript中的箭头函数语法轻松编写,以获得更简洁,更精美的代码:

let greeting = (a) => (b) => a + ' ' + b 

greeting('Hello There')('General Kenobi') 
//returns Hello There General Kenobi

结论 (Conclusion)

While closures may not be as commonly used since Javascript incorporated classes in ES6, they still have their place when it comes to writing clean reusable code. Closures and currying are also important concepts to understand when it comes to functional programming where they essentially serve a similar purpose to private methods in Object Oriented Programming.

自从ES6中的Javascript合并类以来,闭包可能就不那么常用了,但是在编写干净的可重用代码时,闭包仍然占有一席之地。 在函数式编程中, 闭包currying也是重要的概念,它们在本质上与面向对象编程中的私有方法具有相似的作用。

翻译自: https://www.digitalocean.com/community/tutorials/an-introduction-to-closures-and-currying-in-javascript

javascript闭包


http://www.niftyadmin.cn/n/3649413.html

相关文章

GitHub上史上最全的Android开源项目分类汇总(一)

今天晚上配置好GitHub,顺便看看KJFrame,发现有很多的Git资源,下面有很多让人欣喜的效果,大家抓紧搬轮子~~ 浩 2014-11-26 今天在看博客的时候,无意中发现了Trinea在GitHub上的一个项目Android开源项目分类汇总,由于…

Windows安装OpenSSH服务-远程连接Linux

OpenSSH是 SSH (Secure SHell) 协议的免费开源实现。SSH协议族可以用来进行远程控制, 或在计算机之间传送文件。而实现此功能的传统方式,如telnet(终端仿真协议)、 rcp ftp、 rlogin、rsh都是极为不安全的,并且会使用明文传送密码。OpenSSH提…

Picasso的封装(二)

public class PicassoUtils {//默认加载图片public static void loadImaheView(Context mContext, String url, ImageView imageView) {Picasso.with(mContext).load(url).into(imageView);}//默认加载图片(指定大小)public static void loadImageViewSize(Context mContext, S…

如何创建您的第一个Visual Studio代码扩展

介绍 (Introduction) Visual Studio Code is a code editor from Microsoft available on Windows, Linux, and macOS. It offers extensions that you can install through the Visual Studio Code MarketPlace for additional features in your editor. When you can’t find…

网站添加免费SSL证书——HTTPS协议

在添加证书之前首先了解两个概念:SSL和HTTPS。 ▶ SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层与应用层之间对网络连接进行加密。 ▶ …

使用React Native Web构建适合移动设备的Web应用

介绍 (Introduction) Over the years, building web applications that are mobile friendly has become easier with the advent of media queries and the introduction of service workers. Using media queries, we could make web applications that different shapes whe…

sql server和Navicat使用遇到错误解决办法

sql server忘记密码和用户名:http://www.cnblogs.com/xushining/p/3752667.html navicat连接失败:http://blog.csdn.net/lsd123/article/details/5548827

afinal框架(FinalAcitivity,FinalBitmap,FinalDb,FinalHttp 四大模块)

github下载地址:https://github.com/yangfuhai/afinal Afinal是一个android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp。通过finalActivity,我们可以通过注解的方式进行绑定ui和…