I would like to explain the technology of JavaScript closure from a different perspective. Since Java is used for the explanation, basic knowledge of Java (that is, class definition and new knowledge) is required.
――I've read and heard various explanations about closures, but I'm not sure. Or I don't understand at all. But with Java, you know a little? How is it?
Then it is from the conclusion immediately. What is a closure?
Do you say Is that okay? What is a closure?
** A class with only one method (like a mon) **
Oh my god. I told you. I will explain more than I said.
It's quick, but I'd like to start with an example. Closure descriptions often have an example of "let's make a counter!". I don't think this is wrong as an example, so I will explain using the counter as an example here as well. Below is an example of a counter implemented in a closure!
//Make a closure
function createCounter() { //Closure to make a counter
var count=0; //A variable that stores the value of the counter
return function() { //Function declaration inside a function
return ++count; //Increase the value of the counter and then return
};
};
I see. I don't know. JavaScript has a similar grammar to Java, but it's different. .. ..
Let's see how to use it without knowing it.
//Use closures
var cntA=createCounter(); //Creating counter A
console.log(cntA()); //1 is displayed first
console.log(cntA()); //Then 2 is displayed
console.log(cntA()); //Then 3 is displayed
var cntB=createCounter(); //Creating counter B
console.log(cntB()); //1 is displayed first
console.log(cntB()); //Then 2 is displayed
console.log(cntB()); //Then 3 is displayed
[result]
1
2
3
1
2
3
Hmm. .. .. ...... I don't know what closure means. I think that.
Let's take a second look and rewrite this in Java. Then it's really easy. I think, "What? Is that all that?", So seriously.
Now, let's create the exact same thing (that is, the counter class) in Java. Let's go? This is an example of Java!
class Counter //Counter class
{
private int count; //Field containing the value of the counter
public int add() //Method to add
{
count ++; //I'm adding the counter value
return count; //And returning
}
}
From the perspective of those who can use Java, it is a counter no matter how you look at it. The basics of class creation. There are no difficult points. It's easy to understand to death.
Next is how to use it.
Create two instances (cntA
, cntB
) and call the ʻadd ()` method to increase the value.
Not surprisingly, the two instances are independent, so they increase in value separately from each other.
The source looks like this.
//When using
Counter cntA=new Counter(); //Create instance cntA
System.out.println(cntA.add()); //1 is displayed
System.out.println(cntA.add()); //2 is displayed
Counter cntB=new Counter(); //Create instance cntB
System.out.println(cntB.add()); //1 is displayed
System.out.println(cntB.add()); //2 is displayed
[result]
1
2
1
2
No, it was before. Easy easy. Anyone can understand this mon.
so. This is it. This is a closure.
……e? !! This is? Is this a closure? Really? !! Is this the only thing? !!
so. That's all.
In short, (again) closures are ** classes (and their methods) with only one method **. At most, things like this are treated specially with a name like "closure". I don't understand the world of JavaScript. [^ 3]
[^ 3]: I wrote that, but the concept of closures has existed long before JavaScript was born.
If you understand this, you will be able to clearly understand "various things that are said to be the characteristics of closures that you do not understand" in Java.
--You can access variables outside the function from the closure! No, it's not a closure feature in the first place. It's not surprising that a function can access a variable in the outer scope.
--Closers have a function inside a function! In JavaScript, there is no class keyword (until recently) and we use function () instead. If you define a method (also function ()) in it, it means that there is a function inside the function.
-Closers can have a state! In Java, it's natural that an instance variable is alive while the instance is alive. It's not about making noise.
—— Closures can reduce global variables! In Java, there is no concept of global variables in the first place. In Java, it's a natural thing. Originally, I'm wondering if it's a bit of a mess to use global variables.
I wonder ... Isn't it a mon that is bothered to be a feature? I thought or didn't think. It was just this. .. .. ..
So, I think you can understand the concept of closures by now. e? Perfect? with this? Yes. Conceptually, that's all there is to it.
Now that you understand the concept, let's take a look at the closure source written in JavaScript again!
function createCounter() { //Closure to make a counter
var count=0; //A variable that stores the value of the counter
return function() { //Function declaration inside a function
return ++count; //Increase the value of the counter and then return
};
};
var cntA=createCounter();
console.log(cntA());
console.log(cntA());
Hmm. I think I understand a little more than before, but I still don't understand. .. .. I think that. Why is this? This is not because the concept of closures is difficult, but because of JavaScript-specific notation issues **. Closures are conceptually similar to Java classes, but the above sources make full use of the following JavaScript-specific features that are not familiar to Java.
--Can handle functions as values -So you can assign it to a variable or return it as a return value --The function does not have to have a name
That's why it looks more difficult than it really is. This is also a high threshold for Java programmers, so let's take a look.
Now, let's take the example of the counter class created in Java that we saw earlier, and convert the Java-like notation to JavaScript "faithfully".
function counter() //Function class()change to
{
var count=0; //Field containing the value of the counter
this.add=function() //Method to add
{
count ++; //I'm adding the counter value
return count; //And returning
}
}
//When using
var cntA=new counter(); //Creation of closure instance cntA
console.log(cntA.add()); //Add and output the return value to the screen
console.log(cntA.add());
var cntB=new counter(); //Creation of closure instance cntB
console.log(cntB.add()); //Add and output the return value to the screen
console.log(cntB.add());
[result]
1
2
1
2
Oh. This can be understood by the Java brain. It's really "Java-like" JavaScript. There is no problem with the execution result.
so.
This notation is easy for Java programmers to understand, but on the other hand, it's not JavaScript-like, of course.
For example, writing console.log (cntA.add ());
seems redundant.
That's right.
Here, counter ()
plays a class role, but as you can see, it's actually function (), so it's a function in the first place.
So, there is only one method anyway, and if you write console.log (cntA ());
, add () will be called internally, isn't it better? I think.
So, in fact (this is the part that Java shops are not familiar with) ** In JavaScript, the function is an object **. In other words, you can ** assign the function itself to a variable as a value **, or ** return it as a return value **.
So you should implement counter ()
as "a function that returns the ʻadd ()` function itself "! That is (probably) a JavaScript-like idea.
Let's see how to treat a function as a value.
That said, it's not a separate story, it's actually pretty easy.
Specifically, if you take the parentheses at the end of the function (that is, if it is ʻadd (), write ʻadd
), you can treat the function as a value.
You can see it immediately by looking at the example. I think the simplest example looks like this:
//This example does the following:
//-Assign the function itself to a variable
//-Cut the variable in parentheses and call and execute the assigned function.
function hello() //Function definition
{
console.log("hello world!"); //String output
}
var hoge=hello; //Take parentheses and assign the function itself to a variable
hoge(); //You can execute the assigned function by putting parentheses after the variable.
var fuga=hoge; //Try assigning it to another variable.
fuga(); //If you put parentheses on this as well, you can execute the assigned function.
Execution result
hello world!
hello world!
Oh oh. The function is assigned to a variable as a value! It's a pretty cool mechanism to be able to execute it as a function by adding parentheses after the variable.
Let's apply this to the counter example.
You can change it so that when you call counter ()
, ʻadd ()` function ** itself ** is returned.
function counter() // add()Return the function itself
{
var count=0;
this.add=function()
{
count ++;
return count; //Returns the value of the counter
}
return add; // ★★★★add()Is returning the function "itself"
}
//When using
var cntA=counter(); // add()Is returned and add to cntA()Is included
console.log(cntA()); // add()Execution result is displayed
console.log(cntA());
var cntB=counter(); // add()Is returned
console.log(cntB()); // add()Execution result is displayed
console.log(cntB());
How is it? We return functions as return values and assign them to variables! It has become quite a JavaScript-like source!
However, you can actually make it more JavaScript-like. Next up is the "anonymous function".
First, let's take a look at the above source again.
Although it is ʻadd ()provided as a method, it is called only from within
counter (). Then you don't have to give it a name like ʻadd
, right? That is a JavaScript-like idea. So this is an anonymous function.
This is the same as when there is only one person other than yourself in the room, the other person turns around when you say "that" without having to call the name.
By the way, there are some anonymous classes in Java, but if you use them too much ... there is an air in the Java world. The image is that enthusiasts use it with a sloppy face, partly because "readability decreases when using an anonymous class" (personal impression). But in the JavaScript world, anonymous functions are used fairly loosely. Is it a cultural difference between server-side and front-end? </ font>
Well that's fine. Let's use an anonymous function. Specifically, the following parts of the source will be changed.
this.add=function()
{
count ++;
return count; //Returns the value of the counter
}
return add; // ★★★★add()Is returning the function "itself"
Anonymous functions can be used to rewrite the above source as follows:
return function() //★★★★ Write the function to be returned immediately after return
{
count ++;
return count; //Returns the value of the counter
}
It's amazing. Certainly, "ʻadd`" is gone.
It's an old human feeling like me that it's because it's gone, but in the JavaScript world, this kind of thing is pretty normal.
If you are told that you can return the function itself as a return value, you're probably understanding that.
However, if the function that is actually returned is defined on the spot immediately after the return
statement like this, the Java shop will have to feel a sense of discomfort. .. ..
This is probably
var a=5;
return a;
How much to write
return 5;
Isn't it a feeling that it's faster to write?
Now let's look at the whole source again, reflecting the anonymous function.
function counter()
{
var count=0;
return function() //★★★★ Immediately after return, I wrote an anonymous function to return
{
count ++;
return count; //Returns the value of the counter
}
}
When using
var cntA=counter(); //The anonymous function itself is returned and assigned to the variable cntA
console.log(cntA()); //You can call it because it got the name cntA!
console.log(cntA());
var cntB=counter(); //If you assign it to another variable, it will become another instance.
console.log(cntB()); //It works independently
console.log(cntB());
Wow! At the beginning, the source of the JavaScript closure that said "I don't know what you're doing at all even if you look at this" has been created before you know it! What was that? ** If you treat a function as a value or use an anonymous function, this kind of "really JavaScript!" Becomes the source of Kanji **? Was found was found. I see.
I will write the execution result just in case. It is as follows.
1
2
1
2
I will briefly summarize the contents so far.
――Closing is a mechanism like "a class with only one method" in Java. --Conceptually super easy -That's why you can create multiple independent instances ――The reason why it seemed strangely difficult is because of the part that is peculiar to JavaScript, such as returning the function itself or using an anonymous function, which has nothing to do with closures. ――I'll say it again, the concept of closure itself isn't difficult at all, it's easy.
Even if you look at various blogs that explain closures, you will end up here. But maybe the meaning is different. In such a blog and this article.
I think that people who started programming from JavaScript probably came into contact with the idea of "classes and instances" (in a broad sense) after a long time after starting programming. Because, in the world of JavaScript, you can write a lot of code that can be used in the field without knowing that.
I think the reason these people stumble on closures is probably because there are so many barriers to understanding that closures are instances of functions. First of all, "What is an instance?" "What is the first word you hear?" And if you don't know the benefits of class-instances, you don't know the benefits of closures.
There are many questions in the world ** "What makes closures happy?" **, but I think the answer is ** "It can be understood by understanding class-based object orientation" **. I personally think.
On the other hand, if you started programming from Java, you're new from the beginning. There is a class, new, an instance is created, and it can finally be used. This is the structure of Java, a class-based object-oriented language, so if you don't understand it, you can't write Java code at all.
So, on the contrary, if you know Java, you can easily understand closures. I think it's just that there weren't many people who explained from the perspective that "closures are classes with only one method."
So, again. ** What makes closures happy? ** ** I've written it so far, but I think that even Java shops may have this question. However, that is not a question about closures that has been said in the past, but in the sense that "Isn't it okay to be in a class, not a closure?"
In fact, from the contents so far, don't you think, "No, then you should use the class normally instead of closures?" In fact, closures are degraded (that is, limited to only one method) class-instance itself. [^ 2]
[^ 2]: I think there are various things like "I don't like that, isn't it exactly a class?", But that deviates from the purpose of the article.
It doesn't make sense at all because it's treated like a particularly convenient and difficult mechanism. It's super easy if you wonder how difficult it is because everyone says it's difficult and difficult. I think that is the impression of general Java programmers.
In fact, all the benefits of closures (which are said to be) can be solved by implementing them in a class. Furthermore, if you implement it in a class, you can have multiple methods. I gave an example of counters this time, but if you think about it normally and make counters, you may want not only to increase the number but also to reset the counters and, in some cases, decrease them. But no. Closures can only have one method. If that's the case, isn't it better to use the class from the beginning instead of closure? I think there are many people who think that
This is right. It's an individual impression, but maybe this is a difference in values.
In the Java world, it's natural to create classes. Or rather, that's the only option. But in the JavaScript world, you can create classes or closures. If so, I think it's an easy person, but "easy" is subjective. I think that there are quite a lot of people in the JavaScript world who have the feeling that it is troublesome to bother to create a class, or who do not know what a class is in the first place, let alone how to create it. I will.
Another thing I can say is that the world of JavaScript basically revolves around function ().
In the first place, I think that JavaScript has its origins in "a mechanism for describing callback processing that is executed when a certain button is pressed". For example, if you try to implement a simple mechanism that calls a JavaScript function when a button is clicked and checks the contents (although I don't see this kind of writing because it is not popular these days), It's written.
<input type="button" name="submitButton" value="add to" onClick="checkInput();">
ʻOnClick =" checkInput (); " part, which means "when this button is clicked, call the JavaScript function
checkInput (); `".
If you look at it, you can see the atmosphere, but it's a bit unsuitable to describe it as an instance of a class.
Also, recently, jQuery is used for such a part, but when implementing a callback function here, write it like this.
$(function(){
var pushed=false; //Not pressed yet
$('#button').on('click', function() {
if(pushed===false)
{
pushed=true; //It was pushed!
submit(); //Submit
} else { //Prevents submitting twice
alert('Have you pressed it yet?');
}
})
})
This is also a kind of closure, but at such a framework level, "No, I want to implement it in a class!" Is not considered at all in the first place. I don't think there's anything you can't write in a class, but how do you implement it? I think for a moment. If so, is it easier to use closures? I think. Is it a matter of familiarity? Is it?
so,
--Closers were actually easy ――But sometimes I think it would be better to implement it in a class. ――However, closures may be more compatible to move on a web page.
Is that the place? How is it?
I hope Java programmers can now understand closures.
As an aside, don't you think JavaScript is pretty interesting? I think this is a deep world. With SPA (Single-page Application), Web pages will continue to be displayed and have a state, instead of being thrown away every time the screen changes. In that case, I think that a sense that is completely different from conventional JavaScript programming, but rather close to server-side programming, is required. You also have to write classes and objects. Isn't the feeling cultivated in Java really needed? I'm thinking.
Isn't it interesting to take this opportunity to start studying JavaScript in earnest?
Recommended Posts