Prototype Class Object Learning

Source: Internet
Author: User

Copy codeThe Code is as follows:
/* Based on Alex Arnell's inheritance implementation .*/

Var Class = (function (){
// Temporarily store the prototype of the parent
Function subclass (){};

// Create a class
Function create (){
Var parent = null, properties = $ A (arguments );
// Check whether a parent object is specified when a new class is created
// If the parent class is specified, assign the value to the parent
If (Object. isFunction (properties [0])
Parent = properties. shift ();

// Actually used as the returned class. When creating an instance, the initialize method will be called for initialization.
Function klass (){
This. initialize. apply (this, arguments );
}

// Add the addMethods method to klass after calling the create Method
// You can still call the addMethods method to expand the class-level method.
Object. extend (klass, Class. Methods );
// Add two attributes to the returned class: superclass: parent class, subclasses: collection of child classes
Klass. superclass = parent;
Klass. subclasses = [];

// If a parent object is specified during class creation, the klass prototype is directed to the instance of the parent object to implement prototype chain inheritance.
If (parent ){
Subclass. prototype = parent. prototype;
Klass. prototype = new subclass;
// Add a subclass for the parent class to maintain the subclass set of the parent class
Parent. subclasses. push (klass );
}

// Add a method to the new class
For (var I = 0; I <properties. length; I ++)
Klass. addMethods (properties [I]);

// If no initialization method is specified, an empty method is assigned to the initialization method by default.
If (! Klass. prototype. initialize)
Klass. prototype. initialize = Prototype. emptyFunction;

/*
* Modify the constructor of the new class so that the constructor points to itself. Here, I will make a special remark (if the following line is commented out ):
* Var Person = Class. create ();
* Var p1 = new Person ();
* Alert (p1.constructor = Person) // true
* Var Man = Class. create (Person)
* Var m1 = new Man ();
* Alert (m1.constrcutor = Man) // false
* Alert (m1.constrcutor = Person) // true
* Alert (m1.construcctor = p1.constrcutor) // true
*
* Do you see the problem? The Man constructor actually points to the Person constructor.
* The root cause of the problem is klass. prototype = new subclass;
* I will not explain the specific reasons. For more information, see JavaScript language essence and programming practices 155 ~ Page 1
*/
Klass. prototype. constructor = klass;
Return klass;
}

// Add the method used to create a class to the new class, or add a class-level method after the class is created.
Function addMethods (source ){
// Obtain the parent class of the new class
Var ancestor = this. superclass & this. superclass. prototype;
Var properties = Object. keys (source );

// It seems that the following judgment is always true. I don't know why I wrote it. Tell me what I know?
If (! Object. keys ({toString: true}). length ){
// If the toString and valueOf methods are rewritten for the new class, add
If (source. toString! = Object. prototype. toString)
Properties. push ("toString ");
If (source. valueOf! = Object. prototype. valueOf)
Properties. push ("valueOf ");
}

// Traverse all methods in the new class declaration
For (var I = 0, length = properties. length; I <length; I ++ ){
// Property is the function name and value is the function body
Var property = properties [I], value = source [property];
// Determine whether to call a method with the same name as the parent class
If (ancestor & Object. isFunction (value )&&
Value. argumentNames (). first () = "$ super "){
Var method = value;
// This is important!
// Replace the $ super parameter so that this parameter points to the method with the same name as the parent class
// The wrap method of Function is applied here. For details about the wrap method, refer to [Prototype Learning-Function object]
// Method is the newly defined method, so its first parameter is $ super, and the same name method of the parent class is returned from '=' '.'.
// Call the wrap method to replace the $ super parameter with the method of the same name as the parent class. In this way, when the subclass calls $ super (), the method of the same name of the parent class is called.
// The structure here is very good! Worth thinking
Value = (function (m ){
Return function () {return ancestor [m]. apply (this, arguments );};
}) (Property). wrap (method );

// Point the valueOf and toString of the new value (that is, the modified subclass method) to the same name method of the atomic class.
// Here is the legacy problem after the wrap method is called.
Value. valueOf = method. valueOf. bind (method );
Value. toString = method. toString. bind (method );
}
// Add the method to the new class
This. prototype [property] = value;
}

Return this;
}

// Return the callable method of Class
Return {
Create: create,
Methods :{
AddMethods: addMethods
}
};
})();

This class provides two methods: create and addMethods. The above source code comments have clearly been described. Here are some examples to illustrate the usage:
Copy codeThe Code is as follows:
// Declare the Person class and define the initialization method
Var Person = Class. create ({
Initialize: function (name ){
This. name = name;
},
Say: function (message ){
Return this. name + ':' + message;
}
});

// When subclassing, specify the class you want to inherit from
Var Pirate = Class. create (Person ,{
// Redefine the speak method
// Pay attention to the $ super usage here. Take a closer look at the explanations in the source code.
Say: function ($ super, message ){
Return $ super (message) + ', yarr! ';
}
});

Var john = new Pirate ('long john ');
John. say ('ahoy mate ');
//-> "Long John: ahoy matey, yarr! "


Copy codeThe Code is as follows:
Var john = new Pirate ('long john ');
John. sleep ();
//-> ERROR: sleep is not a method
// Every person shocould be able to sleep, not just pirates!

// Here is the addMethods usage, which can be expanded at the class level
Person. addMethods ({
Sleep: function (){
Return this. say ('zzz ');
}
});
John. sleep ();


Copy codeThe Code is as follows:
// Here is the usage of the superclass and subclasses attributes

Person. superclass
//-> Null
Person. subclasses. length
//-> 1
Person. subclasses. first () = Pirate
//-> True
Pirate. superclass = Person
//-> True

Three examples several cover the Class method, for detailed examples see: http://prototypejs.org/learn/class-inheritance

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.