Some people say that javascript is also object-oriented, but it is prototype based. Of course, this is just a conceptual difference. I don’t want to discuss whether js is object-oriented. The key is to explain that although javascript classes act like classes in other languages, the internal implementation mechanism is indeed not very consistent. If you blindly compare the class classes in javascript to classes in other languages, sometimes your mind will be confused.
Let’s first look at a simple piece of code. The general textbook introduces how to create a new class when it comes to this (of course there are more complex methods, but they are essentially the same):
function MyClass(x) {
= x;
}
var obj = new MyClass('Hello class');
alert();
There is no doubt that obj has an x attribute at this time, and the current value is Hello class. But, what exactly is obj? MyClass is just a function, we call it a constructor. In other OO languages, the constructor should be placed inside the class keyword, that is, a class must be declared first. In addition, what is this in the function body? In other OO languages, the concept of this is very clear, which is the current object, because it has declared the class before the constructor is executed, and some fields inside the class have been defined.
Let me first explain that in JavaScript functions, this keyword represents the scope of the function (scope) that calls the function. The concept of scope is not easy to understand. I will explain it below. However, it can be simply considered that it is an object that calls the function. Let’s look at the MyClass function again. What is this inside it?
If we change the code to:
var obj = MyClass('Hello class');
This is completely syntactical. If this code is run in the browser, you can find that this is a window object after debugging. It has nothing to do with obj, obj is still undefined, alert will not have any results. The reason why the original code works is due to the new keyword. The new keyword turns an ordinary function into a constructor. In other words, MyClass is still an ordinary function, and the reason why it can construct an obj is basically the result of new. When the new keyword is present before the function, javascript will create an anonymous object and set the scope of the current function to this anonymous object. Then if you refer to this inside the function, it refers to the anonymous object. Finally, even if the function does not return, it will return the anonymous object. Then obj naturally has the x attribute.
Now this MyClass is a bit like a class. But that's not all new's job. Javascript can also easily implement inheritance - relying on it is also an object. After all, except for the original type, everything is an object, including functions. More importantly, as mentioned earlier, javascript is prototype based, its meaning is that there is no concept of class in javascript, and classes do not exist. The reason why a function expresses a class is based on prototype. prototype can have various properties, including functions. In the process of constructing an object in the previous paragraph, the properties in the function's prototype will be copied to the object one by one before finally returning to the anonymous object. The copy here is a copy reference, not a newly created object. Copying the contents is equivalent to retaining a reference to the prototype of the function that constructs it. Some textbooks vaguely say that all "all objects have a prototype attribute", which is inaccurate. Although it does have a prototype attribute inside, it is invisible to the outside. Only function objects have prototype attributes, and the prototype of function objects has a constructor attribute by default.
Look at the following code:
function MyClass(x) {
= x;
}
var proObj = new MyClass('x');
= proObj;
= 'xxx';
function InheritClass(y) {
= y;
}
var obj = new InheritClass('Hello class');
= 'changed';
= 'Changed Too';
alert();
alert();
The output results are changed and Changed Too. This code shows that the object reserves the reference to the constructor's prototype inside the object. It should be noted that the reference to the constructor's prototype is also reserved in proObj. If you change the code to:
var obj = new InheritClass('Hello class');
= 'I am winner';
= 'changed';
= 'Changed Too';
alert();
alert();
The output is I am winner and Changed Too. In fact, these prototypes are referenced layer by layer, forming a prototype chain. When reading an object's properties, first look for the properties you define. If not, look for the internal implicit prototype attributes layer by layer. However, when writing attributes, it will overwrite its reference, which will not affect the value of prototype.
Let’s introduce closures. First, let’s explain that the closure here is not the same concept as the closure that passes relationships in discrete mathematics. I once thought they were related, but later, I thought about it carefully and it seemed that there was no relationship, it just happened to be the same name. Let's look at the definition first:
Closure
A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
To fully understand closures, you need to have a more thorough understanding of the mechanism of Javascript functions. This mechanism is a bit complicated and cannot be explained clearly in a few words. Interested friends can read Javascript clousures here. Even this article only briefly explains the principle. The general idea is that any function call is executed in an Execution Context, which has a scope object, including local variables, parameters, etc. of the function. In addition, if a function is an internal function, its scope contains the scope of its external function. When an internal function encounters a variable name, it starts from the internal scope and constantly looks at the outer scope. Therefore, if an internal function returns an external function as an object, even if the external function has been executed, since its internal function still has a reference to it, the internal function will not be released because the internal function has the scope of the external function, so the local variables of the external function will not be released. This constitutes a closure.
Let’s first look at a simple piece of code. The general textbook introduces how to create a new class when it comes to this (of course there are more complex methods, but they are essentially the same):
Copy the codeThe code is as follows:
function MyClass(x) {
= x;
}
var obj = new MyClass('Hello class');
alert();
There is no doubt that obj has an x attribute at this time, and the current value is Hello class. But, what exactly is obj? MyClass is just a function, we call it a constructor. In other OO languages, the constructor should be placed inside the class keyword, that is, a class must be declared first. In addition, what is this in the function body? In other OO languages, the concept of this is very clear, which is the current object, because it has declared the class before the constructor is executed, and some fields inside the class have been defined.
Let me first explain that in JavaScript functions, this keyword represents the scope of the function (scope) that calls the function. The concept of scope is not easy to understand. I will explain it below. However, it can be simply considered that it is an object that calls the function. Let’s look at the MyClass function again. What is this inside it?
If we change the code to:
Copy the codeThe code is as follows:
var obj = MyClass('Hello class');
This is completely syntactical. If this code is run in the browser, you can find that this is a window object after debugging. It has nothing to do with obj, obj is still undefined, alert will not have any results. The reason why the original code works is due to the new keyword. The new keyword turns an ordinary function into a constructor. In other words, MyClass is still an ordinary function, and the reason why it can construct an obj is basically the result of new. When the new keyword is present before the function, javascript will create an anonymous object and set the scope of the current function to this anonymous object. Then if you refer to this inside the function, it refers to the anonymous object. Finally, even if the function does not return, it will return the anonymous object. Then obj naturally has the x attribute.
Now this MyClass is a bit like a class. But that's not all new's job. Javascript can also easily implement inheritance - relying on it is also an object. After all, except for the original type, everything is an object, including functions. More importantly, as mentioned earlier, javascript is prototype based, its meaning is that there is no concept of class in javascript, and classes do not exist. The reason why a function expresses a class is based on prototype. prototype can have various properties, including functions. In the process of constructing an object in the previous paragraph, the properties in the function's prototype will be copied to the object one by one before finally returning to the anonymous object. The copy here is a copy reference, not a newly created object. Copying the contents is equivalent to retaining a reference to the prototype of the function that constructs it. Some textbooks vaguely say that all "all objects have a prototype attribute", which is inaccurate. Although it does have a prototype attribute inside, it is invisible to the outside. Only function objects have prototype attributes, and the prototype of function objects has a constructor attribute by default.
Look at the following code:
Copy the codeThe code is as follows:
function MyClass(x) {
= x;
}
var proObj = new MyClass('x');
= proObj;
= 'xxx';
function InheritClass(y) {
= y;
}
var obj = new InheritClass('Hello class');
= 'changed';
= 'Changed Too';
alert();
alert();
The output results are changed and Changed Too. This code shows that the object reserves the reference to the constructor's prototype inside the object. It should be noted that the reference to the constructor's prototype is also reserved in proObj. If you change the code to:
Copy the codeThe code is as follows:
var obj = new InheritClass('Hello class');
= 'I am winner';
= 'changed';
= 'Changed Too';
alert();
alert();
The output is I am winner and Changed Too. In fact, these prototypes are referenced layer by layer, forming a prototype chain. When reading an object's properties, first look for the properties you define. If not, look for the internal implicit prototype attributes layer by layer. However, when writing attributes, it will overwrite its reference, which will not affect the value of prototype.
Let’s introduce closures. First, let’s explain that the closure here is not the same concept as the closure that passes relationships in discrete mathematics. I once thought they were related, but later, I thought about it carefully and it seemed that there was no relationship, it just happened to be the same name. Let's look at the definition first:
Closure
A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).
To fully understand closures, you need to have a more thorough understanding of the mechanism of Javascript functions. This mechanism is a bit complicated and cannot be explained clearly in a few words. Interested friends can read Javascript clousures here. Even this article only briefly explains the principle. The general idea is that any function call is executed in an Execution Context, which has a scope object, including local variables, parameters, etc. of the function. In addition, if a function is an internal function, its scope contains the scope of its external function. When an internal function encounters a variable name, it starts from the internal scope and constantly looks at the outer scope. Therefore, if an internal function returns an external function as an object, even if the external function has been executed, since its internal function still has a reference to it, the internal function will not be released because the internal function has the scope of the external function, so the local variables of the external function will not be released. This constitutes a closure.