JavaScript inheritance Detailed (v) _javascript skills

Source: Internet
Author: User
Tags anonymous extend inheritance instance method

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

Call mode
The invocation is very elegant:
Note: The class, extend, and _super are all custom objects in the code, and we'll explain them later in the code analysis.

var person = class.extend ({
  //init is constructor
  init:function (name) {
this.name = name;
  },
  getName: function () {return
this.name;
  }
});
The employee class inherits
var employee = Person.extend from the person class = ({
  //init is a constructor
  init:function (name, EmployeeID) { c13/>//invokes the constructor
This._super (name) of the parent class in the constructor;
This.employeeid = EmployeeID;
  },
  getemployeeid:function () {return
This.employeeid;
  },
  Getname:function () {
//call method of 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 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 brings a happy smile to countless programmers--hey, a little mushy.
But one piece of code does confuse me for a while:

 
 

I wrote an article in my blog a few days ago devoted to this issue, and I'm interested in turning it over.

The anonymous function that is executed creates a context that avoids introducing global variables (function () {//initializing variables are used to indicate whether the class is currently in the creation phase,//-The prototype method cannot be invoked during the creation phase of the class.//-We have been in the department The third article in the column details the problem//fntest is a regular expression, possibly with a value of (/\b_super\b/or/.*/)//-A test of/xyz/.test (function () {xyz;}) is to detect if the browser supports
  Test parameter is a function of the case//-but I tested ie7.0,chrome2.0,ff3.5 and this test returns TRUE.
  -so I guess this is true for fntest most of the cases: Fntest =/\b_super\b/; var initializing = false, Fntest =/xyz/.test (function () {xyz;})?
  /\b_super\b/:/.*/; Base class constructor//This is window, so this whole piece of code opens up a window-window for the outside world. Class this.
  Class = function () {}; Inheritance method Definition Class.extend = function (prop) {//This place is very confusing, and remember what I mentioned in the second article in this series--this specifically points to what is not defined, but depends on how the function is invoked//- We already know that extend must be called as a method, not as a constructor//-So here this point is not object, but function (that is Class), then This.prototype is the prototype object of the parent class//-Note: _
Super is a prototype object that points to the parent class, and we'll run into that variable var _super = This.prototype in the following code many times.
Inheritance//-NOTE: This is the base class constructor (that is, Class) initializing = True by pointing the subclass's prototype to an instance object of the parent class.
var prototype = new This ();
initializing = false; I think this code has been optimized by the author,So read it very blunt, I will explain in the back for (var name in prop) {Prototype[name] = typeof Prop[name] = = "function" && typeof _super[na
Me] = = "function" && fntest.test (Prop[name])? (function (name, FN) {return function () {var tmp = This._super; this._super = _super[name]; var ret = fn.apply (this, AR
guments);
This._super = tmp;
  return ret;
};
}) (name, Prop[name]): Prop[name]; ///This place can be seen, Resig is very disguise oh//-use a local variable with the same name to overwrite the global variable, very confusing//if you think it is a mouthful, you can use another name, such as function F () instead of function Class ()//- Note: The class here is not called the prototype method init if (!initializing && this.init) in the outermost definition of the base class constructor function class () {//When the class is instantiated) This.ini
T.apply (this, arguments);
The prototype of the//subclass points to an instance of the parent class (the key to completing the inheritance) Class.prototype = prototype;
Fixed constructor pointing error class.constructor = Class;
The subclass automatically obtains the Extend method, Arguments.callee point to the currently executing function class.extend = Arguments.callee;
  return Class;
}; })();

I'll read the for-in loops here and replace the 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 the subclass have a method of the same name, and the method (name) in the subclass invokes the parent class method///-then the method function fn (name, FN) {return funct) is redefined by _super.
            Ion () {//_super The instance method to protect it.
            Personally feel this place is not necessary, because every time you call such a function, you will redefine the this._super.
            var tmp = This._super;
            When executing the instance method name of a subclass, add another instance method _super, which points to the same method of the parent class this._super = _super[name];
            Executes the subclass's method name, noting that in the method body This._super can invoke the same method of the parent class var ret = Fn.apply (this, arguments);
            
            This._super = tmp;
          Returns the execution result return ret;
        }; }//Copy all properties in prop to subclass prototype for (Var name in prop) {//If a function with the same name exists in prop and the parent class, and the letterThe _super method is used in the number, special handling of this method-fn//Otherwise prop[name the method directly to 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 (th
          is, arguments);
        } Class.prototype = prototype;
        Class.constructor = Class;
        Class.extend = Arguments.callee;
      return Class;
    }; })();

Writing here, do you feel that the implementation of Resig is very similar to the jclass that we have achieved in chapter three step-by-step. In fact, before writing this series of articles, I have a certain understanding of prototype, MooTools, ExtJS, Jquery-simple-inheritance, crockford-classical-inheritance these implementations , and most of them have been used in actual projects. In the third chapter to achieve Jclass also referred to the realization of resig, in this to Resig express thanks.
Down we will change the jclass to create the same behavior as the class here.

Our implementation
The Jclass change we made in Chapter three makes the current form of John Resig quite simple, and only needs to modify two or three of the lines:

 (function () {//is currently in the phase of creating class var initializing = false;
      Jclass = function () {};
        Jclass.extend = function (prop) {//If the object that calls the current function (here is a function) is not class, then the parent var baseclass = null;
        if (this!== jclass) {baseclass = this;
            The class (constructor) function F () {//That was created by this call () {//If it is currently at the stage of the instantiation class, invokes 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 a way to invoke the parent class method in the instance object if (BaseClass) {
            This._superprototype = Baseclass.prototype;
          } this.init.apply (this, arguments);
          }//If this class needs to extend if (BaseClass) {initializing = true from other classes;
          F.prototype = new BaseClass ();
          F.prototype.constructor = F;
        initializing = false;

        }//newly created class automatically attaches extend function f.extend = Arguments.callee; Overrides the parent class for the same name as (var name in prop) {if Prop.hasOwnproperty (name) {//If this class inherits from the parent class BaseClass and there is a function name if (BaseClass && T in the parent prototype)
            Ypeof (prop[name]) = = = "function" && typeof (F.prototype[name)) = = = "function" &&
              /\b_super\b/.test (Prop[name])) {//Redefine function name-//First in function context set This._super point to a function of the same name in the parent class prototype Then call function Prop[name], return function result//NOTE: The Self execution function here creates a context in which the context returns another function,//This function can be applied to the variables in this context, which is the closed
              Package (Closure).
              This is a common technique in JavaScript framework development. F.prototype[name] = (function (name, FN) {return function () {this._super = BASECLASS.PR
                  Ototype[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) {//Calling method This._super (name) of the parent class;
      This.employeeid = EmployeeID; Getemployeeidname:function () {//Note: We can also call other functions in the parent class in this way var name = This._superprototype.getna
        Me.call (This, "Employee name:");
      Return name + ", Employee ID:" + This.employeeid;
      }, Getname:function () {//Calling the parent class method 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"

This article is accepted here, and here's a series of articles that everyone can look at

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.