用简单的英语编写 Javascript 闭包和副作用?(分别地)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8129105/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 02:23:24  来源:igfitidea点击:

Javascript closures and side effects in plain English? (separately)

javascriptclosuresside-effects

提问by alexchenco

I've been reading some JavaScript books and I always hear about closures and side effects. For some reason I can't understand what they really are. Can anyone explain to me what they are in plain English plus examples? (as you were explaining it to someone with the programming level of a graphic designer).

我一直在阅读一些 JavaScript 书籍,我总是听说过闭包和副作用。出于某种原因,我无法理解它们到底是什么。谁能用简单的英语和例子向我解释它们是什么?(因为您正在向具有图形设计师编程水平的人解释它)。

回答by Larry OBrien

Side effects are the easier concept. A "pure function" is a function that maps its input value(s) into an output value function plus(x, y) { return x + y; }. A "side effect" is any effect other than that return value. So, for instance:

副作用是更简单的概念。“纯函数”是将其输入值映射到输出值的函数function plus(x, y) { return x + y; }。“副作用”是该返回值以外的任何效果。因此,例如:

function plusWithSideEffects(x, y) { alert("This is a side effect"); return x + y; } 

has the side effect of raising an alert dialog (and requiring user interaction). Every code function has someside effects (they all consume memory and take time, if nothing else), but when people talk about side effects, they are often most concerned with either IO (like the alert dialog above) or the writing of state that lives beyond the execution period of the function.

具有引发警报对话框(并需要用户交互)的副作用。每个代码函数都有一些副作用(它们都会消耗内存和时间,如果没有别的的话),但是当人们谈论副作用时,他们通常最关心的是 IO(如上面的警报对话框)或状态的写入超过函数的执行周期。

The challenge with side effects is that they make functions harder to reason about and to reuse. (It's much easier to reason and reuse functions that are as close to "pure functions" as possible, since they tend to "do one thing well.")

副作用的挑战在于它们使函数更难以推理和重用。(推理和重用尽可能接近“纯函数”的函数要容易得多,因为它们倾向于“做好一件事”。)

回答by outis

Functions with side effects do something other than returning a value (though they may do that as well). If you can replace all function calls for given arguments with the value for those arguments and the program has the same behavior, there are no side effects. This requires that the function always return the same value for given arguments.

具有副作用的函数除了返回一个值之外还做一些事情(尽管它们也可能会这样做)。如果您可以用这些参数的值替换给定参数的所有函数调用,并且程序具有相同的行为,则没有副作用。这要求函数始终为给定参数返回相同的值。

That is, suppose f(1,2) == 12. If you can always replace f(1,2)with 12and the program behaves the same way, then fhas no side effects for those arguments. On the other hand, if in one place f(1,2) == 12and another f(1,2) == 13, then fhas side effects. Similarly, if the program stopped sending an email after replacing f(1,2)with 12, then fhas side effects. Generally, if f(x,y) == z(where z depends on x and y) and you can always replace every f(x,y)call with z, then fhas no side effects.

也就是说,假设f(1,2) == 12。如果您始终可以替换f(1,2)12并且程序的行为方式相同,那么f这些参数就没有副作用。另一方面,如果在一个地方f(1,2) == 12和另一个地方f(1,2) == 13,则f有副作用。同样,如果程序在替换f(1,2)为 12后停止发送电子邮件,则会f产生副作用。通常,如果f(x,y) == z(其中 z 取决于 x 和 y)并且您始终可以用 替换每个f(x,y)调用z,则f没有副作用。

Some simple functions with side effects:

一些有副作用的简单函数:

// doesn't always return the same value
function counter() {
    // globals are bad
    return ++x;
}
// omitting calls to `say` change logging behavior
function say(x) {
    console.log(x);
    return x;
}

回答by Jesse Good

Side-effect:

副作用:

Think of a side-effect as something that does two thingsat once. For example:

将副作用视为同时做两件事的事情。例如:

Classic example of a side effect:

副作用的经典示例:

var i = 1;
var j = i++;

The side effect happens at i++. What happens here is jbecomes 1 and thenigets incremented and becomes 2. In other words, two things happened and the side-effect was that ibecame 2.

副作用发生在i++。这里发生的事情是j变成 1 ,然后i增加并变成 2。换句话说,发生了两件事,副作用是i变成了 2。

Closure:

关闭:

Visualize a chain of links like this: <><><><><><><>. Imagine that the name of this chain of links is called the scope chain. Then imagine that all these links connect objectstogether like this: <>object<>object<>object<>. Now, keep in mind the following:

可视化这样的链接链:<><><><><><><>。想象一下,这个链接链的名字叫做作用域链。然后想象所有这些链接像这样将对象连接在一起:<>object<>object<>object<>。现在,请记住以下几点:

(1) All scope chains begin with the global object.

(1)所有作用域链都以全局对象 开头

(2) When a function is defined, a scope chain for that function is stored.

(2)定义函数时,会存储该函数的作用域链

(3) When a function is invoked, it creates a new object and adds that to the scope chain.

(3)当一个函数被调用时,它会创建一个新对象并将其添加到作用域链中。

Now, please look at the following example:

现在,请看下面的例子:

function counter () { // define counter
                   var count = 0;
                   return function () { return count + 1;}; // define anonymous function
                   };
var count = counter(); // invoke counter

In this example, when counter()is defined, the scope chain for counter looks like this: <>global object<>. Then, when counter()is invoked, the scope chain looks like this: <>global object<>counter object<>. After that, the function with no name (called an anonymous function) inside counter is defined and invoked. The scope chain for the anonymous function once invoked looks like this: <>global object<>counter object<>anonymous function object<>

在这个例子中,当counter()定义时,计数器的作用域链看起来像这样:<>全局对象<>。然后,当counter()被调用时,作用域链看起来像这样:<>全局对象<>计数器对象<>。之后,定义并调用 counter 中没有名称的函数(称为匿名函数)。一旦调用匿名函数的作用域链如下所示:<>全局对象<>计数器对象<>匿名函数对象<>

Heres were the closure part comes in. If you notice, the anonymous function is using the variable countwhich was defined outside of it. The reason is because the anonymous function can access any variables defined in its scope chain. This is what a closure is, a function along with references to any variables in its stored scope chain.

这是闭包部分。如果您注意到,匿名函数正在使用在count其外部定义的变量。原因是匿名函数可以访问在其作用域链中定义的任何变量。这就是闭包,一个函数以及对其存储的作用域链中任何变量的引用。

However, in the above example, once the functions return, the objects created at invocation are discarded so there really is no point. Now look at the following:

然而,在上面的例子中,一旦函数返回,调用时创建的对象就会被丢弃,所以真的没有意义。现在看看以下内容:

function counter () { // define counter
                   var count = 0;
                   function f() { return count + 1;}; // define f
                   return f; // return f
                   };
var count = counter(); // invoke counter

In this example, I am returning a function named fand assign that to the variable count. Now the variable countholds a reference to the entire scope chain and it does not get discarded. In other words the variable count stores the scope chain like this: <>global object<>counter object<>anonymous function object<>. This is the power of closures, you can hold a reference to a scope chain, and call it like this: count().

在此示例中,我返回一个名为的函数f并将其分配给变量count。现在该变量count持有对整个作用域链的引用,并且不会被丢弃。换句话说,变量 count 像这样存储作用域链:<>全局对象<>计数器对象<>匿名函数对象<>。这是瓶盖的力量,你可以拿着一个作用域链的引用,并调用它是这样的:count()

回答by null-none

Exemple

例子

function outer() {
    var outerVar;

    var func = function() {
        var innerVar
        ...
        x = innerVar + outerVar
    }
    return func
}

When outer() die, function func() continue livе and this use practical

当 outer() 死了,函数 func() 继续存活,这个用法很实用

回答by tony wallace

I am new to JavaScript, and will not try to talk of closures. However my newness to JavaScript makes me quite aware of the use of side effect that are impossible in my usual programming language (Erlang).

我是 JavaScript 新手,不会尝试谈论闭包。然而,我对 JavaScript 的陌生让我非常清楚使用我通常的编程语言(Erlang)不可能实现的副作用。

Side effects seem to be a usual way to change state in JavaScript. Take for example this example from the w3cschools.com website:

副作用似乎是在 JavaScript 中改变状态的常用方法。以 w3cschools.com 网站上的这个例子为例:

<script>
function myFunction() {
    document.getElementById("demo").innerHTML = "Paragraph changed.";
}
</script>

Here there is no input parameters or return value, instead the contents of the document get changed as they are global in scope to the function. If you were to write this in Erlang for example, the document would be passed in as a parameter, and the new document state would be returned. A person reading the calling program would see a document passed in and an altered document being returned.

这里没有输入参数或返回值,而是文档的内容被更改,因为它们在函数范围内是全局的。例如,如果你用 Erlang 写这个,文档将作为参数传入,并返回新的文档状态。阅读调用程序的人会看到传入的文档和返回的更改过的文档。

Seeing functions called that to not return explicit new state should alert to programmer to probable use of sideeffects.

看到调用的函数不返回明确的新状态应该提醒程序员可能使用副作用。

回答by mohit kumar

Mainly side effects are the interactions with the outside world from inside of the function. Some examples of the side effects are:- API Calls or HTTP requests, data mutations, Printing to a screen or console, DOM Query/Manipulation. Example :

主要的副作用是从函数内部与外部世界的交互。副作用的一些示例是:- API 调用或 HTTP 请求、数据突变、打印到屏幕或控制台、DOM 查询/操作。例子 :

var a = 12
function addTwo(){
   a = a + 2; // side-effect

}
addTwo()

Closures

关闭

According to MDN,

根据 MDN,

A closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

闭包使您可以从内部函数访问外部函数的作用域。在 JavaScript 中,每次创建函数时都会在创建函数时创建闭包。

Example :

例子 :

function outer(){
  var a = 12; // Declared in outer function 
  function addTwo(){ // closure function
    a = a + 2; // acessing outer function property
    console.log(a)
  }
  addTwo();
 }
 outer()