JavaScript inheritance in detail (v)

Source: Internet
Author: User
Tags instance method

In this chapter, we will analyze John Resig an implementation of JavaScript inheritance-simple JavaScript inheritance.
John Resig is famous as the founder of jquery. Is the author of Pro JavaScript techniques, and Resig will launch a book "JavaScript Secrets" this fall, and look forward to it.

Invocation mode

The calling method is very elegant:
Note: The class, extend, and _super in the code are all custom objects, which we'll explain in a later code analysis.

 var person = Class.extend ({//init is a constructor init:function (name) {this.na            me = name;            }, Getname:function () {return this.name;        }        }); The employee class inherits from the Person class var Employee = Person.extend ({//init is the constructor init:function (name, Emplo                Yeeid) {//The constructor of the parent class is called in the constructor This._super (name);            This.employeeid = EmployeeID;            }, Getemployeeid:function () {return this.employeeid;            }, Getname:function () {//Call the method of the parent class return "Employee name:" + this._super ();        }        });        var Zhang = new Employee ("Zhangsan", "1234");   Console.log (Zhang.getname ()); "Employee Name:zhangsan" 

To be honest, there's really no downside to accomplishing the goal-inheritance-of this series of articles. The method is as concise and straightforward as jquery. Code Analysis

For a nice call, the internal implementation is a lot more complicated, but it's also worth it-a person's thinking gives countless programmers a happy smile-hey, a little creepy.
But one of those codes really confuses me for a while:


The self-executing anonymous function creates a context that avoids the introduction of global variables (function () {///initializing variables to indicate whether the class is currently in the creation phase,//-is not adjustable during the creation of the class Using the prototype method of init//-We have elaborated this problem in the third article in this series//fntest is a regular expression, the possible value is (/\b_super\b/or/.*/)//             -The test for/xyz/.test (function () {xyz;}) is to detect if the browser supports the test parameter as a function//-but I have tested the ie7.0,chrome2.0,ff3.5 and this test returns TRUE.            -So I think this is true for most of the fntest assignment: Fntest =/\b_super\b/; var initializing = false, Fntest =/xyz/.test (function () {xyz;})?            /\b_super\b/:/.*/; Base class constructor//This is the window, so the entire code opens a window to the outside-window. Class this.            Class = function () {}; Inheritance method Definition Class.extend = function (prop) {//This place is very confusing, remember what I mentioned in the second article in this series?//-T He points to what is not defined, but depends on how the function is called//-we already know that extend is definitely called as a method, not as a constructor//-So here this is not the OB Ject, but the function (that is, the class), then This.prototype is the prototype object of the parent class//-Note: _super points to the prototype of the parent classLike, we will encounter this variable var _super = This.prototype in the following code many times;                Inheritance is accomplished by pointing the prototype of a subclass to an instance object of the parent class: This is the base class constructor (that is, Class) initializing = TRUE;                var prototype = new This ();                initializing = false; I think this code has been optimized by the author, so it's very stiff to read, and I'll explain later for (var name in prop) {Prototype[name] = typeof Prop[name] = = "function" && typeof _super[name] = = "function" && fntest.test (prop[n                        AME])?                                 (function (name, FN) {return function () {var tmp = This._super;                                This._super = _super[name];                                var ret = fn.apply (this, arguments);                                This._super = tmp;                            return ret;                        };                        }) (name, Prop[name]):Prop[name]; }//This place can be seen, resig very can disguise oh//-using a local variable with the same name to overwrite the global variable, it is confusing people//-if you feel awkward, you can use another                     A name, such as function F (), instead of function class ()//-NOTE: The class here is not the base class constructor function class defined in the outermost layer () {                        When instantiating a class, call the prototype method init if (!initializing && this.init)                This.init.apply (this, arguments);                The prototype of the}//subclass points to the instance of the parent class (the key to complete the inheritance) Class.prototype = prototype;                Fixed constructor pointing error class.constructor = Class;                The subclass automatically gets the Extend method, Arguments.callee points to the currently executing function class.extend = Arguments.callee;            return Class;        };         })();
Here I will read the for-in loop and replace the self-executing anonymous method with a local function to help us see the truth:
       
 (function () {var initializing = false, Fntest =/xyz/.test (function () {xyz;})?/\b_super\b/:/.*/; This.            Class = function () {};                Class.extend = function (prop) {var _super = This.prototype;                initializing = true;                var prototype = new This ();                initializing = false;                    If the parent class and subclass have a method with the same name, and this method (name) in the child class calls the parent class method through _super/--then redefine this method function fn (name, FN) {                        return function () {//_super The instance method is protected.                        Personally, this place is not necessary because This._super is redefined every time such a function is called.                        var tmp = This._super;                        When you execute the instance method name of the subclass, add another instance method _super, which points to the parent class with the same name method this._super = _super[name];                        The method that executes the subclass name, notice that in the method body This._super can call the parent class with the same name method var ret = fn.apply (this, arguments);                     This._super = tmp;                           Returns the execution result return ret;                }; }//Copy all attributes in prop to subclass prototype for (Var name in prop) {//If a function with the same name exists in prop and parent class, and this The _super method is used in the function, and the method is specially processed-FN//Otherwise this method Prop[name] is directly assigned to the prototype if of the subclass if (typeof Prop[name] = = = "function" && typeof _super[name] = = = "function" && fntest.test (Prop[name])                    {Prototype[name] = fn (name, Prop[name]);                    } else {Prototype[name] = Prop[name];                        }} function Class () {if (!initializing && this.init) {                    This.init.apply (this, arguments);                }} Class.prototype = prototype;                Class.constructor = Class;                Class.extend = Arguments.callee;return Class;        }; })();

Writing here, do you think that the realization of Resig is very similar to the Jclass we implemented in chapter three. In fact, before writing this series of articles, I have to prototype, MooTools, ExtJS, Jquery-simple-inheritance, crockford-classical-inheritance these implementations have a certain understanding , and most of them have been used in actual projects. In the third chapter of the implementation of Jclass also refer to the implementation of Resig, here to Resig express gratitude.
Down we'll change the jclass to have the same behavior as the class here.

Our implementation

It is quite simple to change the jclass that we have achieved in chapter III to the present form of John Resig, only to modify two or three of the lines:

        
(function () {//is currently in the stage of creating the class var initializing = false;            Jclass = function () {};                Jclass.extend = function (prop) {//If the object calling the current function (here is a function) is not class, then the parent class var baseclass = null;                if (this!== jclass) {baseclass = this;                    }//This call creates a class (constructor) function F () {//) if the stage of the instantiated class is currently in, call the INIT prototype function if (!initializing) {///If the parent class exists, the baseprototype of the instance object points to the prototype of the parent class//This provides The way to call the parent class method in an Instance object if (baseclass) {this._superprototype = Baseclass.proto                        Type                    } this.init.apply (this, arguments);                    }}//If this class needs to extend from other classes if (BaseClass) {initializing = true;                    F.prototype = new BaseClass (); F.Prototype.constructor = F;                initializing = false;                }//The newly created class automatically attaches the Extend function f.extend = Arguments.callee;                        Overrides the parent class with the same name function for (var name in prop) {if (Prop.hasownproperty (name)) {  If this class inherits from the parent class BaseClass and the parent prototype has the same name as the function name if (BaseClass && typeof                        (Prop[name]) = = = "function" && typeof (F.prototype[name]) = = = "function" &&  /\b_super\b/.test (Prop[name])) {//Redefine function name-// First in the function context set This._super point to the same name function in the parent prototype//and then call the function Prop[name], return the function result//NOTE:                            The self-executing function here creates a context, which returns another function,//The variable in this context can be applied in this function, which is the closure (Closure).                            This is a common technique used in JavaScript framework development. F.prototype[name] = (function (name, fn) {return function () {this._super = Baseclass.proto                                    Type[name];                                Return fn.apply (this, arguments);                            };                        }) (name, Prop[name]);                        } else {F.prototype[name] = Prop[name];            }}} return F;        };        })();            Modified jclass var person = jclass.extend ({init:function (name) {this.name = name;            }, Getname:function (prefix) {return prefix + this.name;        }        }); var Employee = Person.extend ({init:function (name, EmployeeID) {//Call method of parent class thi                S._super (name);            This.employeeid = EmployeeID; }, Getemployeeidname:function () {// Note: We can also call other functions in the parent class in this way var name = This._superprototype.getname.call (This, "Employee name:");            Return name + ", Employee ID:" + This.employeeid;            }, Getname:function () {//calls the method of the parent class return This._super ("Employee name:");        }        });        var Zhang = new Employee ("Zhangsan", "1234");   Console.log (Zhang.getname ()); "Employee Name:zhangsan" Console.log (Zhang.getemployeeidname ()); "Employee Name:zhangsan, employee id:1234"

JavaScript inheritance in detail (v)

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.