Simple JavaScript inheritance

Source: Internet
Author: User
I want to extract the essence of inheritance technology to a simple, reusable, easy to understand, and without any dependencies. In addition, I want to make this result simple and very useful. Here is an example of the effect I want: varPersonClass. extend ({init:... SyntaxHighlighter. all ();

I want to extract the essence of inheritance technology to a simple, reusable, easy to understand, and without any dependencies. In addition, I want to make this result simple and very useful. Here is an example of what I want:
Var Person = Class. extend ({
Init: function (isDancing ){
This. dancing = isDancing;
},
Dance: function (){
Return this. dancing;
}
});
 

Var Ninja = Person. extend ({
Init: function (){
This. _ super (false );
},
Dance: function (){
// Call the inherited version of dance ()
Return this. _ super ();
},
SwingSword: function (){
Return true;
}
});

Var p = new Person (true );
P. dance (); // => true

Var n = new Ninja ();
N. dance (); // => false
N. swingSword (); // => true

// Shocould all be true
P instanceof Person & p instanceof Class &&
N instanceof Ninja & n instanceof Person & n instanceof Class

Note the following points in this implementation:
1. Creating a constructor class must be simple (in this case, simply providing an init method can work );
2. To create a new 'class', you must extend the existing class (sub-class;
3. All 'class' are inherited from an ancestor: Class. Therefore, if you want to create a new Class branch, the new Class branch must be a subclass of the Class;
4. The most challenging thing is to obtain the methods that have been overwritten but must be provided (the context of these methods is correctly set ). The above uses this. _ super () method to call the original init () and dance () Methods of the Person parent class.
I am very satisfied with this result: it helps to enhance the 'classe' concept as a structure, maintain simple inheritance, and allow method calls to the parent class.
Simple class construction and inheritance
There is an implementation of the above Code (moderate scale and good comments)-about 25 lines of upstream and downstream code. Feedback is good and widely accepted.

// Specified red by base2 and Prototype
(Function (){
Var initializing = false, fnTest =/xyz/. test (function () {xyz ;})? /\ B _super \ B /:/.*/;
 

// The base Class implementation (does nothing)
This. Class = function (){};
 
// Create a new Class that inherits from this class
Class. extend = function (prop ){
Var _ super = this. prototype;

// Instantiate a base class (but only create the instance,
// Don't run the init constructor)
Initializing = true;
Var prototype = new this ();
Initializing = false;

// Copy the properties over onto the new prototype
For (var name in prop ){
// Check if we're overwriting an existing function
Prototype [name] = typeof prop [name] = "function "&&
Typeof _ super [name] = "function" & fnTest. test (prop [name])?
(Function (name, fn ){
Return function (){
Var tmp = this. _ super;

// Add a new. _ super () method that is the same method
// But on the super-class
This. _ super = _ super [name];

// The method only need to be bound temporarily, so we
// Remove it when we're done executing
Var ret = fn. apply (this, arguments );
This. _ super = tmp;

Return ret;
};
}) (Name, prop [name]):
Prop [name];
}

// The dummy class constructor
Function Class (){
// All construction is actually done in the init method
If (! Initializing & this. init)
This. init. apply (this, arguments );
}

// Populate our constructed prototype object
Class. prototype = prototype;

// Enforce the constructor to be what we recommend CT
Class. prototype. constructor = Class;

// And make this class extendable
Class. extend = arguments. callee;

Return Class;
};
})();

In my opinion, the two most difficult problems are "initializing/Don't call init" and "create super method ". I would like to briefly introduce this to give you a better understanding of what is done in this method.
Initialization
In order to use the prototype of a function to simulate inheritance, we use the traditional technology to create a prototype for the parent class function and assign it to the prototype of the subclass. Without considering the above content, its implementation is similar to this:
Function Person (){}
Function Ninja (){}
Ninja. prototype = new Person ();
// Allows for instanceof to work:
(New Ninja () instanceof Person
The challenge here is that we need to use the benefits of instanceof, instead of simply considering the consumption of instantiating the Person parent class and running its constructor. To sum up the effects of both, there is a variable initializing in our code. No matter when we want to instantiate a class (the only purpose is) as the prototype value, this variable is set to true.


Therefore, when talking about the actual constructor, we need to be sure that we are not in an initialization mode, but conditional execution of the init method:
If (! Initializing)
This. init. apply (this, arguments );
In particular, the init method can run a variety of startup code that consumes a lot (connect to the server and create DOM elements, who knows), so it will be very good to bypass this final work.
Super Method
When you perform Inheritance, you create a class to inherit from the parent class. A common requirement is that you need to obtain the method that has been overwritten by you. As a result, in this special implementation, it is a new temporary method. _ super. This method is the only way to reference the same method of the parent class through the subclass method.
For example, if you want to use this technology to call the constructor of the parent class, you can do this:
Var Person = Class. extend ({
Init: function (isDancing ){
This. dancing = isDancing;
}
});
 

Var Ninja = Person. extend ({
Init: function (){
This. _ super (false );
}
});

Var p = new Person (true );
P. dancing; // => true

Var n = new Ninja ();
N. dancing; // => false

Implementing this function is a multi-step process. At the beginning, note that we are used to extend the literal volume of an existing class (for example, it is passed to Person. the one in extend needs merge to the basic new Person instance (the structure of this instance has been described before ). In this merge process, we made a simple check: is the attribute we are merging (merge) Not a function? Is it a function that we are replacing? If the conditions are true, we need to do something to create a way to make our parent method still work.
Note that we have created an anonymous closure (which returns a function) to encapsulate the new parent class enhancement method. At the beginning, we need to be a qualified citizen, save the reference to the old this. _ super (if it does exist, ignore it), and restore it after we finish the corresponding work. This is useful when a variable with the same name already exists (do not expect it to be replaced unexpectedly ).
Next we will create a new _ super method, which is just a reference to the method that already exists in the prototype of the parent class. Fortunately, we do not need to make additional changes or redefine the scope, when a function is an attribute of our object, its context environment will be automatically set (this will point to our instance rather than the parent class ).
Finally, we call our original method. After we restore _ super to its original state and return a value from the function, it will complete its work (or possibly use _ super ).
For the above situation, there are already several methods to achieve similar results (I have seen a method through arguments. callee is used to bind the parent class method to the method itself), but I feel that my technology provides the best combination of practicality and simplicity.
In my work, I want to cover more essential and detailed information hidden behind JavaScript prototype, but with regard to the implementation of this Class, I want more people to try it and use it. I think there is much more to say about concise code (easier to learn, expand, and download), so I think it is a good start to understand the basics of JavaScript class construction and inheritance. (End)
 

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.