Comprehensive understanding of Object-oriented JavaScript (from IBM) _javascript tips

Source: Internet
Author: User

Today's JavaScript is a great way to rely on a variety of applications that are deeply dependent on the day. Web programmers have become accustomed to using a variety of good JavaScript frameworks to quickly develop WEB applications, ignoring the learning and understanding of native JavaScript. So, often the case is that many of the programmers who have done for many years JS development of closures, functional programming, prototypes are always unclear, even if the use of the framework, the code organization is very bad. This is a manifestation of the lack of understanding of native JavaScript language features. To master JavaScript, first of all, we must discard some other high-level languages such as Java, C # and other class object-oriented thinking interference, comprehensively from a functional language point of view to understand the JavaScript prototype object-oriented features. After grasping this point, it is possible to further use the language. This article is suitable for groups: programmers who have used JS framework but lack understanding of the nature of JS language, have experience in language development such as Java and C + +, programmers who are ready to learn and use JavaScript, and have been ambiguous about whether JavaScript is object-oriented, but want to know the truth of JS enthusiasts 。

Re-understanding of object-oriented

In order to illustrate that JavaScript is a thorough object-oriented language, it is necessary to start from the object-oriented concept to explore some of the object-oriented concepts:

All things are objects

object has encapsulation and inheritance attributes
Message communication is used between objects and objects, and there is information hiding
Based on these three points, C + + is a half object-oriented process language because, although he implements the encapsulation, inheritance and polymorphism of the class, there are global functions and variables of a non object nature. Java, C # is a complete object-oriented language that organizes functions and variables in the form of classes so that they cannot be detached from objects. But here the function itself is a process, just attached to a class.

However, object-oriented is just a concept or programming idea, it should not rely on the existence of a language. For example, Java uses object-oriented thinking to construct its language, it implements the mechanism of class, inheritance, derivation, polymorphism, interface and so on. But these mechanisms are just a means of implementing object-oriented programming, not necessarily. In other words, a language can choose the right way to implement the object-oriented according to its own characteristics. So, since most programmers first learn or use advanced compiled languages such as Java and C + + (Java is generally interpreted as a compiler), they have a preconceived acceptance of the object-oriented implementation of "class", so that when learning a scripting language, The concept of object-oriented language is used to judge whether the language is an object-oriented language, or whether it has object-oriented characteristics. This is also one of the important reasons that prevents programmers from learning and mastering JavaScript in depth.

In fact, the JavaScript language implements object-oriented programming in a way called a prototype (prototype). The following is a discussion of the differences in the way in which the object-oriented (class-based) object-oriented and prototype (prototype-based) object-oriented approach constructs the objective world.

Object-oriented and prototype-based object-oriented comparison of class-oriented objects

In a class-oriented object-oriented approach, objects (object) depend on classes (class) to produce them. In a prototype-oriented object-oriented approach, objects (object) rely on constructors (constructor) to use The prototype (prototype) is constructed. Give an example of an objective world to illustrate the differences in cognition in two different ways. For example, a factory building a car, on the one hand, workers must refer to a project drawing, design to specify how the car should be made. Engineering drawings hereare like classesin a language, and cars are based on this class (class) On the other hand, workers and machines (equivalent to constructor) use a variety of components such as engines, tires, and steering wheels (equivalent to the various properties of prototype) to construct the car.

There is, in fact, a debate as to who has expressed the object-oriented idea more thoroughly in both ways. But the author thinks that the prototype object oriented is a more thorough object-oriented way, the reasons are as follows:

First of all, the object in the objective world is the result of the construction of other objects, and abstract "drawings" can not produce a "car", that is, the class is an abstract concept rather than an entity, and the production of objects is an entity;

Secondly, according to the most basic object-oriented principle of everything, class is not an object in itself, but the constructor (constructor) and prototype (prototype) in the archetypal way are itself the objects constructed by other objects in a prototype way.

Again, in class-oriented object-oriented languages, the state of an object is held by an object instance (instance), and the object's behavior methods (method) are held by the class that declares the object, and only the structure and methods of the object can be inherited, and in the archetypal object-oriented language, the object's behavior, The state belongs to the object itself and can be inherited together (reference resources), which is also closer to the objective reality.

Finally, class object-oriented languages such as Java, to make up for the inconvenience of not using global functions and variables in a process-oriented language, allow the declaration of static (static) and static methods in the class. In fact, the objective world does not exist the so-called static concept, because all things are objects! In the prototype object-oriented language, in addition to the built-in object (Build-in object), the existence of global objects, methods or attributes is not allowed, and there is no static concept. All language elements (primitive) must be dependent on the existence of an object. However, due to the features of functional language, the object on which language elements are dependent varies with the context of the runtime (runtime), which is embodied in the change of this pointer. It is this characteristic that is closer to the natural view that all things have their own, that the universe is the root of all living things. window is similar to the concept of the universe in Listing 1 of the program.

Listing 1. object's context Dependency

Copy Code code as follows:

<script>
var str = "I am a String object, I declare here, but I am not independent!" "
var obj = {des: "I am an object, and I declare here that I am not independent." " };
var fun = function () {
Console.log ("I'm a Function Object!") Who calls me, who I belong to: ", this);
};

Obj.fun = fun;

Console.log (this = = window); Print True
Console.log (window.str = = str); Print True
Console.log (window.obj = = obj); Print True
Console.log (Window.fun = = = Fun); Print True
Fun (); Print I am a Function Object! Who calls me, who I belong to: window
Obj.fun (); Print I am a Function Object! Who calls me, who I belong to: obj
Fun.apply (str); Print I am a Function Object! Who calls me, who I belong to: Str
</script>


After accepting the fact that an object-oriented existence is called a method based on a prototype implementation, we can now delve into how ECMAScript constructs its own language in this way.

The most basic object oriented

ECMAScript is a thoroughly object-oriented programming language (reference Resource), and JavaScript is one variant (variant). It provides 6 basic data types, namely Boolean, number, String, Null, Undefined, Object. In order to achieve object-oriented,ECMAScript designed a very successful data structure-JSON (JavaScript Object notation), a classic structure that can be separated from the language and become a widely used format (reference resources).

It should be said that ECMAScript with basic data types and JSON construction syntax can already implement object-oriented programming. Developers can arbitrarily construct an object by literal declaration (literal notation) , assign a value directly to an attribute that does not exist, or delete the attribute with delete (Note: The Delete in JS Keyword is used to delete an object property and is often mistaken for delete in C + +, which is used to release objects that are no longer in use, such as Listing 2 of the program.

Listing 2. Literal (literal notation) object declaration

Copy Code code as follows:

var person = {
Name: "John",
Age:26,
Gender: "Male",
Eat:function (stuff) {
Alert ("I'm eating" + stuff);
}
};
Person.height = 176;
Delete person["age"];

In the actual development process, most beginners or to JS application is not too high requirements of developers are basically only used ECMAScript definition of this part of the content, can meet the basic development needs. However, this code reusability is very weak, and other implementation of inheritance, derivation, polymorphism, such as class-oriented object-oriented strong-type language is somewhat withered, can not meet the complex JS application development. So ECMAScript introduces prototypes to solve object inheritance problems.

To construct an object using the function builder

In addition to the literal declaration (literal notation) method, ECMAScript allows objects to be created through Constructors (constructor) . Each constructor is actually a functionobject that contains a "prototype" property to implement a prototype based inheritance ( prototype-based inheritance) and shared properties. objects can be created by means of the "new keyword + constructor call", as in Listing 3:

Listing 3. To create an object using the constructor (constructor)

Copy Code code as follows:

The constructor person itself is a function object
function person () {
Here you can do some initialization work
}
It has a property called prototype.
Person.prototype = {
Name: "John",
Age:26,
Gender: "Male",
Eat:function (stuff) {
Alert ("I'm eating" + stuff);
}
}
To construct an object using the New keyword
var p = new person ();

Because the inventor of early JavaScript was trying to make this language a relationship with the famous Java (although now everyone knows that the two are the relationship between Lei Feng and Lei Feng Tower), the new keyword is used to qualify constructor calls and create objects so that they look similar in syntax to the way Java creates objects. But it should be pointed out that the new meaning of the two languages has nothing to do with it, because the mechanism of the object construction is completely different. It is precisely because of this grammatical similarity, many people accustomed to the class-oriented object-oriented language in the creation of the way programmers, it is difficult to thoroughly understand the JS object prototype construction method, because they always do not understand in the JS language, why "function name can be used as a class name" phenomenon. In essence, JS here just borrowed the keyword new, that's all; in other words, ECMAScript can use other non-new expressions to create an object using the call constructor.

Thorough understanding of the prototype chain (prototype chain)

In ECMAScript, each object created by the constructor has an implicit reference (implicit reference)that points to the constructor prototype property value, which is referred to AS Prototype (prototype). Further, each prototype can have an implicit reference to its own prototype (that is, the prototype's prototype), and so on, this is called the prototype chain (prototype chain) (reference resources). In a specific language implementation, each object has a __proto__ attribute to implement an implicit reference to the stereotype. This is illustrated in Listing 4 of the program.

Listing 4. __proto__ property and implicit reference to an object

Copy Code code as follows:

function person (name) {
THIS.name = name;
}
var p = new person ();
Object has an implicit reference to the constructor's prototype property, so it prints true here
Console.log (p.__proto__ = = = Person.prototype);

The prototype itself is an object, so his implicit reference points to the
The prototype property of the Object constructor, printing true
Console.log (person.prototype.__proto__ = = = Object.prototype);

The constructor person itself is a function object, so print true here
Console.log (person.__proto__ = = = Function.prototype);

With the prototype chain , you can define a so-called attribute-hiding mechanism and implement inheritance through this mechanism. ECMAScript stipulates that when you assign a value to an object's properties, the interpreter looks for the first object in that object's prototype chain that contains the attribute (note: The prototype itself is an object, then the prototype chain is a chain of objects). The first object in the prototype chain of the object is the object itself. Conversely, if you want to get the value of an object property, the interpreter will naturally return the object property value that first has the attribute in the prototype chain of that object. Figure 1 says the hidden mechanism in this:


Figure 1. The mechanism of attribute hiding in prototype chain

In Figure 1, Object1->prototype1->prototype2 makes up the prototype chain of object Object1, and according to the above attribute hiding mechanism, we can clearly see Property4 attribute and Prototy in Prototype1 object. The Property3 property in the Pe2 object is hidden. Understanding the prototype chain, it will be very easy to understand the prototype in JS Inheritance implementation principle, listing 5 is the use of prototype chain to implement a simple example of inheritance.

Listing 5. Using prototype chain Horse->mammal->animal to realize inheritance

Copy Code code as follows:

Declaring the Animal object Builder
function Animal () {
}
Point the Animal prototype attribute to an object,
can also be directly understood as the prototype of the specified Animal object
Animal.prototype = {
Name:animal ",
weight:0,
Eat:function () {
Alert ("Animal is eating!");
}
}
Declaring the Mammal Object Builder
function mammal () {
THIS.name = "mammal";
}
Specifies that the mammal object's prototype is a Animal object.
This is actually the prototype chain between creating the mammal object and the Animal object
Mammal.prototype = new Animal ();

Declaring the Horse object Builder
function horse (height, weight) {
THIS.name = "Horse";
This.height = height;
This.weight = weight;
}
Specifies the prototype of the horse object as a Mamal object, continuing to build the prototype chain between horse and mammal
Horse.prototype = new mammal ();

Re-Specify the Eat method, which overrides the Eat method inherited from the Animal prototype
Horse.prototype.eat = function () {
Alert ("Horse is eating grass!");
}
Validate and understand the prototype chain
var horse = new Horse (100, 300);
Console.log (horse.__proto__ = = = Horse.prototype);
Console.log (horse.prototype.__proto__ = = = Mammal.prototype);
Console.log (mammal.prototype.__proto__ = = = Animal.prototype);

The key to understanding the implementation of object prototype inheritance logic in Listing 5 is Horse.prototype = new mammal () and mammal.prototype = new Animal (). First, the result on the right side of the equation is to construct a temporary object and then assign the object to the prototype property of the object on the left side of the equation. That is, the newly created object on the right is the prototype of the left object. The reader can then replace the two equations with their own comprehension in the equation in the last two lines of the corresponding program listing 5 code.

An implementation method of JavaScript class inheritance

From code Listing 5, we can see that, based on the inheritance of the prototype, although the implementation of code reuse, but its language is loose and not fluent, poor readability, not conducive to the implementation of extension and the source code for effective organization and management. Admittedly, class-style inheritance is more robust in language implementation, and has obvious advantages in building reusable code and organization architecture programs. This makes programmers want to find a way to encode a class-style inheritance style in JavaScript. From an abstract point of view, since both class inheritance and prototype inheritance are designed to implement object-oriented objects, and the carrier language they implement is equivalent in computational power (because Turing's computational power is equivalent to the computational power of the Lambda calculus), can you find a transformation So that the prototype inheritance language implements the style of class inheritance encoding through this transformation?

At present, some mainstream JS framework provides this kind of conversion mechanism, also namely class declaration method, such as Dojo.declare (), Ext.entend () and so on. Using these frameworks, users can easily and amicably organize their own JS code. In fact, prior to the advent of many frameworks, JavaScript master Douglas Crockford first used three functions to extend the function object to implement this transformation, and the implementation details of it can be (refer to resources). There are also famous base.js (reference resources) that are implemented by Dean Edwards . It is worth mentioning that the father of JQuery, John resig , after the length of the audience, with less than 30 lines of code to achieve their own simple inheritance. Declaring a class with the Extend method it provides is simple. Listing 6 is an example of a declaration using the simple Inheritance Library implementation class. The last line of the print output statement is the best explanation for the simple inheritance implementation of class-style inheritance.

Listing 6. Using simple inheritance to implement class inheritance

Copy Code code as follows:

Declaring the Person class
var person = class.extend ({
_issleeping:true,
Init:function (name) {
This._name = name;
},
Issleeping:function () {
return this._issleeping;
}
} );
Declare the programmer class and inherit the person
var programmer = Person.extend ({
Init:function (name, issleeping) {
Calling the parent class constructor
This._super (name);
Set your own state
this._issleeping = issleeping;
}
} );
var person = new Person ("John");
var diors = new Programmer ("Zhangjiang male", false);
Print True
Console.log (Person.issleeping ());
Print False
Console.log (Diors.issleeping ());
All true here, so print true
Console.log (person instanceof person && person instanceof Class
&& diors instanceof Programmer &&
Diors instanceof person && diors instanceof Class);

If you have a good understanding of prototypes, function constructors, closures, and context-based this, it is not difficult to understand the implementation of simple inheritance. In essence, the var person = class.extend (...) In this statement, the person on the left actually obtains a constructor that is returned by Class calling the Extend method, or a reference to a function object. Along this line of thinking, we continue to explain how simple inheritance is doing this, thus realizing the transformation from prototype inheritance to class-style inheritance. Figure 2 is the source code for simple inheritance and its accompanying annotations. For ease of understanding, use Chinese to add lines to the code.

Figure 2.Simple Inheritance Source code Analysis



Aside from the second part of the code, the whole coherent review of the first and third chapters found that the fundamental purpose of the Extend function is to construct a new constructor with a new stereotype attribute. We can not help but lament John resig 's master handwriting and its grasp of the nature of the JS language of the delicate degree. As for John Resig How to think of such a subtle implementation, interested readers can read this article (reference resources), which provides a detailed description of the original design of simple inheritance thinking process.

JavaScript Private Member implementation

So far, if you're still skeptical about JavaScript-oriented objects, the suspicion must be that JavaScript does not implement object-oriented information hiding, that is, private and public. Unlike other class-oriented object-oriented methods that explicitly declare private public members, the information hiding of JavaScript is implemented by closures. See Procedure Listing 7:

Listing 7. Using closures to implement information hiding

Copy Code code as follows:

Declaring the User Builder
function User (pwd) {
Defining private properties
var password = pwd;
Defining Private methods
function GetPassword () {
Returns the password in the closure
return password;
}
A privileged function declaration, used by other public methods of the object to access private members through this privileged method
This.passwordservice = function () {
return GetPassword ();
}
}
Public member Declaration
User.prototype.checkPassword = function (pwd) {
return This.passwordservice () = = pwd;
};
Verifying the concealment of
var u = new User ("123456");
Print True
Console.log (U.checkpassword ("123456"));
Print undefined
Console.log (U.password);
Print True
Console.log (typeof U.gepassword = = "undefined");

JavaScript must rely on closures to implement information hiding, which is determined by its functional language characteristics. This article does not discuss the two topics of functional language and closures, just as you understand the context-based this in JavaScript by default. About implementing information hiding in JavaScript,Douglas crockford is more authoritative and detailed in the article "Private members in JavaScript" (reference resources).

Conclusion

JavaScript is considered to be the most misunderstood programming language in the world, because it wears the cloak of the C-language family and behaves as a LISP-style functional language; Without a class, it actually implements the object-oriented. In order to have a thorough understanding of the language, it is necessary to open up the cloak of its C language and return to the point of functional programming, and discard the object-oriented concept of the original class to learn to comprehend it. With the popularity of WEB applications in recent years and the rapid development of JS language itself, in particular the emergence of the background JS engine (such as based on V8 Nodejs, etc.), you can foresee, originally just as a toy to write the effect of the page JS will get a broader development world. This development trend, but also to JS programmers put forward higher requirements. Only by thoroughly understanding the language can it be possible to play her power in a large JS project.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.