Any programming proposes code reuse. Otherwise, if you have to write a new program every time you develop a new program or write a new function, it will be useless. However, code reuse also has good and bad aspects. The next two In the following articles, we will discuss code reuse. The first article, avoid articles, refers to trying to avoid using these patterns because they may cause some problems; the second article is recommended articles, referring to This is the mode recommended for everyone to use, generally there will be no problems.
Mode 1: Default mode
Code reuse of the commonly used default mode is often problematic. This mode uses the constructor of Parent() to create an object and This object is assigned to the prototype of Child(). Let’s take a look at the code:
function inherit(C, P) { C.prototype = new P();}
// Parent constructor function Parent(name) { this.name = name || 'Adam';}
// Add say function to the prototype Parent.prototype .say = function () { return this.name;};
// Child constructor is empty function Child(name) {}
// Execute inheritance inherit(Child, Parent); var kid = new Child ();console.log(kid.say());
// "Adam"var kiddo = new Child();kiddo.name = "Patrick";console.log(kiddo.say());
// "Patrick"// Disadvantage: parameters cannot be passed into the Child constructor var s = new Child('Seth'); console.log(s.say());
// "Adam" The disadvantage of this mode is that Child cannot pass in parameters, so it is basically useless.
Mode 2: Borrowing the constructor This mode is that Child borrows the Parent's constructor for apply, and then passes the child's this and parameters to the apply method. :
// Parent constructor function Parent(name) { this.name = name || 'Adam';}
// Add the say function to the prototype Parent.prototype.say = function () { return this.name;};
// Child constructor function Child( name) { Parent.apply(this, arguments);}var kid = new Child("Patrick");console.log(kid.name);
// "Patrick"// Disadvantages: No constructor Inherit the say method console.log(typeof kid.say);
// The disadvantage of "undefined" is also obvious. The say method is not available because it is not inherited.
Mode 3: Borrow the constructor and set the prototype The above two modes have their own shortcomings, so how to remove the shortcomings of both? Let's try it:
// Parent constructor function Parent(name) { this.name = name || 'Adam';}// Add the say function to the prototype Parent.prototype.say = function () { return this .name;};//Child constructor function Child(name) { Parent.apply(this, arguments);}Child.prototype = new Parent();var kid = new Child("Patrick");console.log( kid.name); // "Patrick"console.log(typeof kid.say); // functionconsole.log(kid.say()); // Patrickconsole.dir(kid);delete kid.name;console.log (kid.say()); // "Adam" runs and everything is normal, but have you noticed that the Parent constructor is executed twice, so although the program is usable, the efficiency is very low.
Mode 4: Shared prototype Shared prototype means that Child and Parent use the same prototype. The code is as follows:
function inherit(C, P) { C.prototype = P.prototype;}
// parent constructor function Parent (name) { this.name = name || 'Adam';}
// Add the say function to the prototype Parent.prototype.say = function () { return this.name;};
// Child construction Function function Child(name) {}inherit(Child, Parent);var kid = new Child('Patrick');console.log(kid.name);
// undefinedconsole.log(typeof kid.say);
// functionkid.name = 'Patrick'; console.log(kid.say());
// Patrickconsole.dir(kid); It's definitely the same, the parameters of Child were not received correctly.
Mode 5: Temporary Constructor First borrow the constructor, then set Child's prototype to an instance of the borrowed constructor, and finally restore the Child prototype 's constructor. The code is as follows:
/* Closure*/var inherit = (function () { var F = function () { }; return function (C, P) { F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; CC.prototype.constructor = C; }} ());function Parent(name) { this.name = name || 'Adam';}// Add say to the prototype Function Parent.prototype.say = function () { return this.name;};// Child constructor function Child(name) {}inherit(Child, Parent);var kid = new Child();console.log(kid .name); // undefinedconsole.log(typeof kid.say); // functionkid.name = 'Patrick';console.log(kid.say()); // Patrickvar kid2 = new Child("Tom"); console.log(kid.say()); console.log(kid.constructor.name); // Childconsole.log(kid.constructor === Parent); // false The problem remains the same, Child cannot receive parameters normally.
Mode 6: klass
For this mode, let’s start with the code:
var klass = function (Parent, props) { var Child, F, i; //
1. // New constructor Child = function () { if (Child.uber && Child.uber.hasOwnProperty("__construct")) { Child.uber.__construct.apply(this, arguments); } if (Child .prototype.hasOwnProperty("__construct")) { Child.prototype.__construct.apply(this, arguments); } }; //
2. // Inherit ParentParent = Parent || Object; F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); Child.uber = Parent.prototype; ChildChild.prototype.constructor = Child; /
3. // Add implementation method for (i in props) { if (props.hasOwnProperty(i)) { Child.prototype[i] = props[i]; } }
// return the "class" return Child;};var Man = klass(null, { __construct: function (what) { console.log("Man's constructor"); this.name = what; }, getName: function () { return this.name; }});var first = new Man('Adam') ;
// logs "Man's constructor" first.getName();
// "Adam" var SuperMan = klass(Man, { __construct: function (what) { console.log("SuperMan's constructor"); }, getName: function () { var name = SuperMan.uber.getName.call(this); return "I am " name; }});var clark = new SuperMan('Clark Kent');clark.getName() ;
// "I am Clark Kent"console.log(clark instanceof Man);
// trueconsole.log(clark instanceof SuperMan);
Looking at it makes you feel a little dizzy. , to put it nicely, the syntax and specifications of this pattern are the same as those of other languages. Are you willing to use it?
Summary Although the above six modes achieve certain functions in certain special circumstances, they all have their own shortcomings, so in general, everyone should avoid using them.