JavaScript Framework Design Factory _JAVASCRIPT Skills

Source: Internet
Author: User
Tags inheritance

Class and inheritance in JavaScript, the advent of JavaScript has reached the threshold of large-scale development, before the ECMASCRIPT4, tried to introduce classes, modules and other things, but because too much introduction too many features, make JavaScript smoke, resulting in rejection. But only the class is deferred to ES6. So far, JavaScript has no real-world class. But we can simulate the class, for some time, the class factory is the standard of the framework, this chapter will introduce various classes of implementation, to facilitate everyone in their own framework or choose the style of their favorite.

1.javascript Support for classes

In other languages, instances of a class are created by the constructor new. As a language that deliberately imitates Java. JavaScript has the new operator, and all functions can act as constructors. Constructors are no different from normal methods. Browsers in order to build its blossoming ecological circle, such as node,element,htmlelement,htmlparagraphelement, it is obvious that using inheritance to facilitate the sharing of some methods or properties, So JavaScript borrowed prototypes from other languages as a mechanism. Prototype is present on every function as a special object attribute. When a function is new through the new operator to its "child"-"instance", the object named instance has all the members of the prototype object of the function, thus implementing all instance objects sharing a set of methods or properties. What JavaScript calls "Class" is by modifying this prototype object to distinguish between native objects and their other defined "classes." In the browser, the class node is based on object modification, and the element is based on node, and HtmlElement is based on element .... Relative to our work business, we can create our own classes to achieve reuse and sharing.

  function A () {

  }
  a.prototype = {
    aa: "AA",
    method:function () {
    }
  };
  var a = new A;
  var b = new A;
  Console.log (A.aa = = = B.aa);
  Console.log (A.method = = = B.method)

Generally, we call the method defined on the prototype the prototype method, which is shared by all instances, which is good and bad, and for the sake of differentiation, JavaScript allows us to specify its methods directly within the constructor, which is called the privileged method. If it is a property, it is called a privileged attribute. Each of them is a copy of each instance, and does not affect each. As a result, we typically put the shared method of manipulating data in the prototype, placing the private attribute in the privileged attribute. But put it on this, or let people access it arbitrarily, put it within the scope of the function body. At this point it becomes a veritable private property.

  function A () {
    var count = 0;
    THIS.AA = "AA";
    This.method = function () {return
      count;
    }
    This.obj = {}
  }
  a.prototype = {
    aa: "AA",
    method:function () {

    }}
  ;
  var a = new A;
  var b = new A;
  Console.log (A.aa = = = B.aa);//true because the value of AA is the base type, the comparison value
  console.log (a.obj = = b.obj)//false reference type, which is recreated every time the function body is entered, so it is different.
  Console.log (A.method = = = B.method);//false

A privileged method or property is simply a method or property that obscures the prototype, so you can approach a prototype method or property of the same name by deleting the privileged method.

  Delete A.method;
  Delete B.method;
  Console.log (A.method = = A.prototype.method);//true
  console.log (A.method = = B.method);//true

In the Java language, both the prototype method and the privileged method are attribute instance methods, and in Java there is something called class methods and class attributes. They are also very simple to simulate using JavaScript, directly defined on the function.

  A.METHOD2 = function () {}//class method
  var c = new A;
  Console.log (C.METHOD2); Undefined

Next, let's look at the implementation of the inheritance, which says that there is something on the prototype, and there is something about its instance, whether it was added later, or the whole prototype was replaced. If we were to replace this prototype object with the prototype of another class, it would be easy to get all the prototype members of that class.

  function A () {};
  A.prototype = {
    aaa:1
  }
  function B () {};
  B.prototype = A.prototype;
  var B = new B;
  Console.log (B.AAA); => 1;
  A.PROTOTYPE.BB = 2;
  Console.log (B.BB)//=> 2;

Because it refers to the same object, this means that we modify the prototype of Class A, which is equivalent to the prototype of Class B. Therefore, we cannot assign an object to two classes. There are two ways to do this.

Method 1: Assign the stereotype members of the parent class to the prototype of the subclass
Method 2 is that the prototype of a subclass is not derived directly from the parent class, first assigning the prototype of the parent class to a function, and then the instance of the function as the prototype of the subclass.

Method One, we usually want to realize mixin such method, some books call copy inheritance, the advantage is simple direct, the disadvantage is not through instanceof verification. Prototype.js's Extend method is used to do this.

  function extend (DES, source) {//des = destination for
    (var. source)
      Des[property] = Source[property]; return
    des;
  

Method Two, on the prototype of the brain, so called the prototype inheritance. Here's a template.

  function A () {};
  A.prototype = {
    aa:function () {
      alert (1)
    }
  }
  function Bridge () {

  };
  Bridge.prototype = A.prototype;

  function B () {}
  B.prototype = new Bridge ();

  var a = new A;
  var B = new B;

  Console.log (A = = B)//false The prototype method for successfully separating
  the prototype console.log (A.prototype = = B.prototype)//true subclass to share the parent class
  Console.log ( A.aa = = = B.aa); Dynamically adding a new method to the parent class
  a.prototype.bb = function () {
    alert (2)
  }
  //true, the method that inherits the parent class
  b.prototype.cc = function () {
    alert (3)
  }
  //false The parent class does not necessarily have a new instance of the subclass
  Console.log (a.cc = = b.cc)
  // And it is able to function normally through JavaScript itself with the validation mechanism instanceof
  Console.log (b instanceof A);//true
  Console.log (b instanceof B); True

Method II through INSTANCEOF verification, ES5 built this method to implement the prototype inheritance, it is object.create, if not considered the second parameter, it is approximately equal to the following code.

  Object.create = function (o) {
    function F () {}
    f.prototype = O;
    return new F ();
  }

The above method requires that the prototype of a parent class be passed as an argument and then the prototype of the subclass is returned

Still, we're missing something--subclasses are not just inheriting from the parent's legacy, they should have something of their own, in addition, prototype inheritance doesn't allow subclasses to inherit the members and privileged members of the parent class. These we all have to add manually, such as class members, we can through the above extend method, privileged members we can in the subclass constructor, through the apply implementation.

  function inherit (init, Parent, proto) {
    function Son () {
      parent.apply (this, argument);//Inherit privileged members
      of parent class first Init.apply (this, argument); In executing its own constructor
    }
  //Because Object.create is forged by us, avoid using the second parameter
  Son.prototype = Object.create ( parent.prototype,{});
  Son.prototype.toString = Parent.prototype.toString; Handling Iebug
  Son.prototype.valueOf = Parent.prototype.valueOf;//processing iebug
  Son.prototype.constructor = Son;// Make sure that the constructor is pointing normally, not object
  extend (Son, proto);//Add the unique prototype member of the subclass return
  Son;

Next, do a set of experiments to test the retrospective mechanism of the example below. When we access a property of an object, he first looks for his privileged members, returns if he has the same name, does not find the prototype, and then does not find the prototype of the parent class ... We try to modify its prototype temporarily to see that its properties become that.

  function A () {

  }
  a.prototype = {
    aa:1
  }
  var a = new A;
  Console.log (A.AA); =>1

  //Replace all of its prototypes
  A.prototype = {
    aa:2
  }
  console.log (A.AA);//=>1

  // So we think that each instance has a constructor method that points to its constructor
  //And that the constructor has exactly our prototype, does the JavaScript engine backtrack the attribute by that route?
  function B ()

  {}
  B.prototype = {
    aa:3
  }
  a.constructor = B;
  Console.log (A.AA)//1 indicates not affected

So the class instance definitely goes back through another channel and looks at the ECMA specification. Each object has an internal property [[prototype]], which holds the prototype object referenced by the constructor that we are new to. In standard browsers and IE11, it exposes a call to the __proto__ property to access it. Therefore, as long as the __proto__ above code does not move, A.aa always firm not Yi's return 1.

Take another look at what happens when new is in operation.

1. Created an empty object instance
2.instance.__proto__ = Intanceclass.prototype
3. The This = instance inside the constructor
4. Execute the code in the constructor
5. Determine there is no return value, no return value will return the default value of undefined, if the return value is a composite data type, then return directly, otherwise return this
So we have the following results.

  function A () {
    console.log (THIS.__PROTO__.AA);//1
    This.aa = 2
  }
  a.prototype = {aa:1}
  var a = new a;< C6/>console.log (A.AA)
  a.__proto__ = {
    aa:3
  }
  console.log (A.AA)//=>2
  delete A. aa;//Delete privilege properties , exposing a property of the same name on the prototype chain
  Console.log (A.AA)//=>3

With __proto__, we can design the prototype design to be more simple, we still take the example above to change, to experiment

  function A () {}
  A.prototype = {
    aa:1
  }
  function Bridge () {}
  Bridge.prototype = a.prototype;< C20/>function B () {}
  B.prototype = new Bridge ();
  B.prototype.constructor = B;
  var B = new B;
  b.prototype.cc = function () {
    alert (3)
  }
  //string.prototype = = new String (). __proto__ => True
  Console.log (b.prototype.__proto__ = = a.prototype)//true
  console.log (b.__proto__ = = B.prototype);//true 
  Console.log (b.__proto__.__proto__ = = = A.prototype); True to get the prototype object of the parent class

Because B.__proto__.constructor is B, and B's prototype is derived from bridge, and Bride.prototype = A.prototype, in turn, when we define, b.prototype.__proto__ = A.prototype, you can easily implement two classes of inheritance.

The __proto__ attribute has been added to the ES6, so it can be prevented by bold use

2. Implementation of various types of factories.

We demonstrated the implementation of various inheritance methods in the previous section, but they were messy. We want to provide a special method, as long as users pass in the appropriate parameters, or in a certain simple format can create a class. especially subclasses.

Because the mainstream framework of the class factory relies too much on their complex tool functions, and a sophisticated class factory is only around the hundred

A rather ingenious library, P.js.

Https://github.com/jiayi2/pjs

Use version: Https://github.com/jiayi2/factoryjs

This is a fairly ingenious library, especially when calling the method of the parent class with the same name, it throws the prototype of the parent class directly in front of you, and even _super is saved.

  var p = (function (prototype, ownproperty, undefined) {return function P (_superclass/* = Object */, definition) {/
   /Handle the case where no superclass is given if (definition = = = undefined) {definition = _superclass;
  _superclass = Object;
  }//C is the class to be returned. When called, creates and initializes a instance of C, unless//' This ' are already an instance of C, then just I
  Nitializes ' this ';
  Either way, returns the instance of C that is initialized. Todo:the Chrome Inspector shows all created objects as ' C '//rather than ' Object '. Setting the. Name property seems to//have no effect.
  Is there a way to override this behavior?
   Function C () {var self = this instanceof c. this:new Bare;
   Self.init.apply (self, arguments);
  return self; }//C.bare is a class with a noop constructor.
  Its prototype'll is//the same as C, so that instances of C.bare are instances of C. ' New Myclass.bare ' then Creates new instances of C without//calling. Init ().

  function Bare () {} c.bare = Bare; 
  Extend the prototype Chain:first use Bare to create a//uninitialized instance of the superclass, then set up Bare
  To create instances the This class.
  var _super = Bare[prototype] = _superclass[prototype];

  var proto = Bare[prototype] = C[prototype] = C.P = new Bare;

  Pre-declaring the iteration variable for the loop below to save//a ' var ' keyword after minification var key;

  Set the constructor property on the prototype, for convenience proto.constructor = C;

  C.extend = function (def) {return P (C, Def);} return (C.open = function (def) {if (typeof def = = "function ') {//Call the defining function with all Argume
    NTS your need//extensions captures the return value.
   def = Def.call (c, Proto, _super, C, _superclass); }//... and extend it if (typeof def = = = ' object ') {for (key in Def) {if (Ownproperty.call) (Def, Key)) {Proto[key] = Def[key]; }}//If no init, assume we ' re inheriting from a Non-pjs class, so//default to using the superclass con
   Structor. if (! ('

   Init ' in proto) Proto.init = _superclass;
  return C;
 }) (definition); }//As a minifier optimization, we ' ve closured in a few helper functions//And the String ' Prototype ' (C[P) is very much s

 Horter than C.prototype)}) (' Prototype ', ({}). hasownproperty);

We tried to create a class:

  var Dog = P (function (proto, Superproto) {
    proto.init = function (name) {//constructor
      this.name = name;
    }
    Proto.move = function (meters) {//Prototyping method
      Console.log (THIS.name + "moved" + meters + "M.")
    }
  );
  var a = new Dog ("AAA")
  var b = new Dog ("BBB");//No instance Change
  a.move (1);
  B.move (2);

We can try to create a more concise way of defining this in the present situation.

  var Animal = P (function (proto, Superproto) {
    proto.init = function (name) {//constructor
      this.name = name;
    }
    Proto.move = function (meters) {//Prototyping method
      Console.log (THIS.name + "moved" + meters + "M.")
    }
  );
  var a = new Animal ("AAA")
  var b = new Animal ("BBB");//No instance Change
  a.move (1);
  B.move (2);
  //...............
  var Snake = P (Animal, function (Snake, Animal) {
    snake.init = function (name, eyes) {
      Animal.init.call (this, arguments); Dispatching parent class Builder
      This.eyes = 2;
    }
    Snake.move = function () {
      console.log (' slithering ... ');
      Animal.move.call (this, 5); Dispatching parent class with the same name Method
    }
  });
  var s = new Snake ("Snake", 1);
  S.move ();
  Console.log (s.name);
  Console.log (S.eyes);

Private property demo, because put in the function body centrally defined, so safe and reliable!

  var Cobra = P (Snake, function (Cobra) {
    var age = 1;//Private property
    //Here you can also write private methods
    Cobra.glow = function () {//Grow up
      ret Urn age++;
    }
  });
  var c = new Cobra ("Cobra");
  Console.log (C.glow ()); 1
  console.log (C.glow ());//2
  Console.log (C.glow ());//3

The above mentioned is the entire content of this article, I hope you can enjoy.

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.