JavaScript is a very low entry threshold language, and even a technician who has never had access to JavaScript, can write a simple and useful program code within hours.
But if so you're jumping to conclusions: JavaScript is a simple language. Then you are wrong. To write High-performance code, you also need to have the basics of a senior programmer.
A Java or C + + programmer may not necessarily be able to write high-performance JavaScript code, but it is easier to write high-performance JavaScript code.
The simplicity of JavaScript is based on its "broad-minded" inclusiveness. When it declares, you do not need to specify a type or even any type of transformation. It is object oriented, but it has no class limit. It is a liberal and very rigorous language, if you are a liberal, then, embrace JavaScript!
Object-oriented programming (OOP) is a popular programming method. But JavaScript oop, compared to Java, C + + has a lot of the same, the main embodiment of its different ways of inheritance. JavaScript is inherited based on prototype prototype. All objects are based on a prototype chain, which eventually traces to object objects.
There is no need to discuss the differences between how JavaScript is inherited and how other languages are inherited. The main discussion is how to encapsulate the JavaScript class to better manage and maintain the underlying code, reduce repetitive code, and better modular programming.
Here are some of the better class encapsulation libraries found on several github:
First, My-class
Project Address: Https://github.com/jiem/my-class
First look at basic usage:
A, create a new class
Copy Code code as follows:
(function () {
New class
Varperson=my. Class ({
Add a static method
static:{
Age_of_majority:18
},
Constructors
Constructor:function (name,age) {
This.name=name;
This.age=age;
},
Instance method
Sayhello:function () {
Console.log (' Hellofrom ' +this.name+ '! ');
},
Instance method
Drinkalcohol:function () {
This.age<person.age_of_majority?
Console.log (' tooyoung! drinkmilkinstead! '):
Console.log (' Whiskeyorbeer? ');
}
});
Exposing to namespaces
Mylib.person=person;
})();
Varjohn=newmylib.person (' John ', 16);
John.sayhello ();//log "hellofromjohn!"
John.drinkalcohol ();//log "tooyoung! drinkmilkinstead! "
b, inheriting a class
Copy Code code as follows:
(function () {
Dreamer Inherit person
Vardreamer=my. Class (person,{
Construction method
Constructor:function (Name,age,dream) {
Dreamer.Super.call (This,name,age);
This.dream=dream;
},
Instance method
Sayhello:function () {
Supersayhello.call (this);
Console.log (' idreamof ' +this.dream+ '! ');
},
Instance method
Wakeup:function () {
Console.log (' wakeup! ');
}
});
Super Access Parent class
Varsupersayhello=dreamer.super.prototype.sayhello;
Exposing to global namespaces
Mylib.dreamer=dreamer;
})();
Varsylvester=newmylib.dreamer (' Sylvester ', the ' eatingtweety ');
Sylvester.sayhello ();//log "hellofromsylvester! idreamofeatingtweety! "
Sylvester.wakeup ();//log "wakeup!"
C, add a new method to the class
Copy Code code as follows:
Add a new method to Mylib.dreamer
My.extendclass (mylib.dreamer,{
Add a static method
static:{
S_dongsomething:function () {
Console.log ("dosomething!");
}
},
Add Instance method
Touchthesky:function () {
Console.log (' Touchingthesky ');
},
Add Instance method
Reachthestars:function () {
Console.log (' sheissopretty! ');
}
});
D, a way to implement a class
Copy Code code as follows:
Declare a new class
Mylib.imaginarytraveler=my. Class ({
Travel:function () {console.log (' travelingonacarpet! ');},
Crossoceans:function () {console.log (' sayinghitomobydick! ');}
});
(function () {
Dreamer method of implementing Imaginarytraveler by inheriting person
Vardreamer=my. Class (person,imaginarytraveler,{
Construction method
Constructor:function (Name,age,dream) {
Dreamer.Super.call (This,name,age);
This.dream=dream;
}
//...
});
Exposing to global namespaces
Mylib.dreamer=dreamer;
})();
Varaladdin=newdreamer (' Aladdin ');
Aladdininstanceofperson;//true
Aladdininstanceofimaginarytraveler;//false
Aladdin.travel ();
Aladdin.wakeup ();
Aladdin.sayhello ();
If you're afraid to forget the new operator
Copy Code code as follows:
Varperson=my. Class ({
Youcannowcalltheconstructorwithorwithoutnew
Constructor:function (name,city) {
if (!) ( Thisinstanceofperson))
Returnnewperson (name,city);
This.name=name;
This.city=citye;
}
});
Here's a look at My.class's source code resolution:
My. Class implementation is basically like this, if there is only one parameter, then the declaration is a base class, which is used to declare new classes of methods and genera and constructors. It is not inherited, but it can be inherited.
The idea of inheritance is that if there are two arguments, the first argument is inherited, the second argument is used to declare the methods and properties of the new class and the constructor, and it can also be inherited.
If there are more than three parameters, then the first argument is the inherited parent class, and the last parameter is declared with the method and property of the new class and the constructor. The middle parameter is the method of extending the new class with the class. Of course, you can extend the new method through My.extendclass.
At the same time, the class library provides support for both COMMONJS and browsing environments!
Copy Code code as follows:
/*globalsdefine:true,window:true,module:true*/
(function () {
Namespaceobject
varmy={};
Ensure AMD modules are available
if (typeofdefine!== ' undefined ')
Define ([],function () {
Returnmy;
});
ElseIf (typeofwindow!== ' undefined ')
Ensure client availability
Window.my=my;
Else
Ensure background is available
Module.exports=my;
//============================================================================
@methodmy. Class
@paramsbody: Object
@paramsSuperClass: Function,implementclasses:function...,body:object
@returnfunction
My. Class=function () {
Varlen=arguments.length;
varbody=arguments[len-1];//the last parameter is the method that specifies itself
varsuperclass=len>1?arguments[0]:null;//The first parameter refers to the inherited method, and both instances and static parts inherit
varhasimplementclasses=len>2;//If there is a third argument, then the second one is Implementclass, where the instance object is actually inherited
Varclass,superclassempty;
Guaranteed Construction Method
if (body.constructor===object) {
Class=function () {};
}else{
Class=body.constructor;
Ensure that the back does not cover constructor
Deletebody.constructor;
}
Handling Superclass Parts
if (superclass) {
Implementation of instance attribute inheritance in middleware
Superclassempty=function () {};
Superclassempty.prototype=superclass.prototype;
Class.prototype=newsuperclassempty ();//prototype inheritance, dereferencing
class.prototype.constructor=class;//Guarantee Constructor
class.super=superclass;//Parent Object Access interface
static method inheritance, overloaded superclass method
Extend (Class,superclass,false);
}
Processing the implementclass part, in fact, only inherits the instance attribute part, except superclass#arguments[0] #和body #arguments[length-1]#
if (hasimplementclasses)
for (vari=1;i<len-1;i++)
Implement is an inherited instance attribute section, overloading the Parent object Implementclass method
Extend (Class.prototype,arguments[i].prototype,false);
The process itself declares the body part, statically to the static specified, the instance part to delete the static part
Extendclass (Class,body);
Returnclass;
};
//============================================================================
@methodmy. Extendclass
@paramsClass: Function,extension:object,?override:boolean=true
Varextendclass=my.extendclass=function (class,extension,override) {
Static part inherits static part
if (extension. STATIC) {
Extend (class,extension. Static,override);
Guaranteed instance parts do not inherit static methods
Deleteextension. STATIC;
}
Instance property following inheritance instance Department
Extend (class.prototype,extension,override);
};
//============================================================================
Varextend=function (obj,extension,override) {
Varprop;
In fact, the flase here is to show that the method of overriding the parent object
if (Override===false) {
for (propinextension)
if (!) ( Propinobj))
Obj[prop]=extension[prop];
}else{
This does not actually overwrite the parent object's methods, including ToString
for (propinextension)
Obj[prop]=extension[prop];
if (extension.tostring!==object.prototype.tostring)
obj.tostring=extension.tostring;
}
};
})();
Second, Klass
Project Address: Https://github.com/ded/klass
See how to use First:
A, create a new class
Copy Code code as follows:
Declaring a class
Varperson=klass (function (name) {
This.name=name
})
. statics ({//static method
Head: ':) ',
Feet: ' _|_ '
})
. Methods ({//instance method
Walk:function () {}
})
b, inheriting a class
Copy Code code as follows:
Superhuman Inherit person
Varsuperhuman=person.extend (function (name) {
Automatic invocation of the constructor method of the parent class
})
. Methods ({
Walk:function () {
Explicitly declares the walk method of invoking the parent class
THIS.SUPR ()
This.fly ()
},
Fly:function () {}
})
Newsuperhuman (' Zelda '). Walk ()
C, a literal way of declaring a class
Copy Code code as follows:
Varfoo=klass ({
foo:0,
Initialize:function () {
This.foo=1
},
Getfoo:function () {
Returnthis.foo
},
Setfoo:function (x) {
This.foo=x
Returnthis.getfoo ()
}
})
D, a way to implement a class
Because sometimes you might want to overwrite or mix an instance method, you can do this:
Copy Code code as follows:
Can pass a literal amount to inherit
Varalien=superhuman.extend ({
Beam:function () {
THIS.SUPR ()
Beamintospace
}
})
Varspazoid=newalien (' Zoopo ')
if (Beamisdown) {
Overwrite Beam method
Spazoid.implement ({
Beam:function () {
THIS.SUPR ()
Fallbacktojets
This.jets ()
}
})
}
Let's take a look at Klass source code resolution:
Klass's basic design idea is very clear, strongly imitate other language's inheritance way. For example, a subclass constructor invokes the constructor method of the parent class, and it can explicitly declare the method that invokes the parent class.
This judgment is based on a regular match: fntest=/xyz/.test (function () {xyz;})? /\bsupr\b/:/.*/keyword "Super"
If the display declares a method to invoke the parent class, then when declaring the method, it wraps into a function that calls the parent class method internally and returns the same value, to the current class method.
On the other hand, the construction method is also more flexible. If the declared initialize is displayed, then this is the construction method. Otherwise, if the parameter is a function, then it is constructed as a method, otherwise the method of constructing the parent class is used.
Add a static method statics by adding an instance method methods the instance's implements and static methods.
Inheritance is implemented through the extend of the parent class.
At the same time, the class library provides support for both COMMONJS and browsing environments!
Copy Code code as follows:
/**
*klass.js-copyright@dedfat
*version1.0
*https://github.com/ded/klass
*followoursoftwarehttp://twitter.com/dedfat:)
*mitlicense
*/
!function (context,f) {
Fntest is used to verify that the method of calling the Super parent class can be found by regular
Varfntest=/xyz/.test (function () {xyz;})? /\bsupr\b/:/.*/,
Noop=function () {},
Proto= ' prototype ',
Isfn=function (o) {
Returntypeofo===f;
};
Base class
Functionklass (o) {
Returnextend.call (typeofo==f?o:noop,o,1);
}
Packaged into a function that borrows the same method as Super
Functionwrap (K,FN,SUPR) {
Returnfunction () {
Cache Original This.super
VARTMP=THIS.SUPR;
Temporarily transforming This.super into a method of using the same name as super above
The explicit declaration for O (fntest.text (FN) ==true) is to use the same method as Super
THIS.SUPR=SUPR[PROTO][K];
Borrow execution and save return value
Varret=fn.apply (this,arguments);
Restore the original This.super
this.supr=tmp;
Returns the return value to ensure that the return value after the wrap is consistent with the original
Returnret;
};
}
If O and super have a method of the same name, and O explicitly declares a method that borrows the same name for super, it is wrap into a pending function for use
If there is no explicit declaration to use the method of the same name for Super, or an O-unique method, or the method is directly
Functionprocess (WHAT,O,SUPR) {
for (Varkino) {
If the method is not inherited, it is executed by the method annotation rule, which is eventually put into the what
if (O.hasownproperty (k)) {
What[k]=typeofo[k]==f
&&typeofsupr[proto][k]==f
&&fntest.test (O[k])
? Wrap (K,O[K],SUPR): O[k];
}
}
}
The implementation of the inheritance method, Fromsub is used to control whether the inheritance, the above Klass inside Fromsub is 1, indicating that not inherited, constructors do not borrow super execution
Functionextend (o,fromsub) {
NoOp as the media class implements the dereference of the prototype inheritance
Noop[proto]=this[proto];
Varsupr=this,
Prototype=newnoop (),//Create instance object for prototype inheritance, dereference
Isfunction=typeofo==f,
_constructor=isfunction?o:this,//If O is a construction method, otherwise the constructor is determined by this
_methods=isfunction? {}:o,//If O is a {...} The methods should be put into the FN prototype, if there is a initialize is a constructor, if O is a function is determined by the above _constructor O is a constructor
Fn=function () {//Because kclass with kclass, so ultimately actually returns FN,FN the constructor for the new class
1 if O is {...} will be filtered directly by methods and added to the FN prototype, and if there is a initialize in the FN prototype, then there is initialize, then it is the construction method
2 If O is function,methods nothing is added to the FN prototype, but _constructor will accept o when the constructor
3 if O is {...}, and there is no initialize inside, then this is this when the constructor, if determined by call in Klass, obviously the constructor is NoOp, if the constructor is the constructor of the parent class in the non-basic class
Since o is not a function that does not automatically invoke the constructor of the parent class, it simply treats the constructor of the parent class as the constructor of the current class----This is due to the point of this
Console.log (this);
if (this.initialize) {
This.initialize.apply (this,arguments);
}else{
Calling the parent class construct method
If the above 3,o is not a function, the constructor method of the parent class is not invoked
The underlying class does not have a parent class, and the parent class constructor method is not invoked
fromsub| | ISFN (o) &&supr.apply (this,arguments);
Call this class construct method
Reference above 2,3 either NoOp or O
Console.log (_constructor==noop);
_constructor.apply (this,arguments);
}
};
Interface for constructing a prototype method
Fn.methods=function (o) {
Process (PROTOTYPE,O,SUPR);
Fn[proto]=prototype;
Returnthis;
};
Implement new class prototypes to ensure the constructor of new classes
Fn.methods.call (fn,_methods). Prototype.constructor=fn;
Ensure that new classes can be inherited
Fn.extend=arguments.callee;
Add instance method or static method, Statics: Static method, implement instance method
Fn[proto].implement=fn.statics=function (O,OPTFN) {
Guarantee O is an object, if O is a string, then it is a case of adding a method if O is an object description is bulk added
Because we're going to copy it from O.
o=typeofo== ' string '? (function () {
varobj={};
OBJ[O]=OPTFN;
Returnobj;
} ()): O;
Add instance method or static method, Statics: Static method, implement instance method
Process (THIS,O,SUPR);
Returnthis;
};
RETURNFN;
}
Backstage use, Nodejs
if (typeofmodule!== ' undefined ' &&module.exports) {
Module.exports=klass;
}else{
Varold=context.klass;
Conflict prevention
Klass.noconflict=function () {
Context.klass=old;
Returnthis;
};
Front browser with
Window.kclass=kclass;
Context.klass=klass;
}
} (this, ' function ');
third, there is also a simple implementation
Implementation of the idea is very simple, that is, the use of ECMAScript5 prototype inheritance Object.create method, encapsulated into a method, if not supporting the ECMASCRIPT5 environment, translation degradation to
Copy Code code as follows:
Functionf () {};
F.prototype=superctor.prototype;
CTOR.PROTOTYPE=NEWF ();
Ctor.prototype.constructor=ctor;
Similarly, except that the last parameter is the current class's method declaration, the other parameters are inherited by the parent class and need to be cycled, but when handled here is relatively simple and does not involve overwriting. You can add your own hands.
Copy Code code as follows:
varclass= (function () {
/**
*inheritsfunction. (Node.js)
*
* @paramctorsubclass ' sconstructor.
* @paramsuperctorsuperclass ' sconstructor.
*/
Varinherits=function (ctor,superctor) {
Explicitly specify the parent class
Ctor.super_=superctor;
ECMAScript5 stereotype inheritance and dereference
if (object.create) {
Ctor.prototype=object.create (superctor.prototype,{
constructor:{
Value:ctor,
Enumerable:false,
Writable:true,
Configurable:true
}
});
}else{
Stationary degradation of non-object.create method
Functionf () {};
F.prototype=superctor.prototype;
CTOR.PROTOTYPE=NEWF ();
Ctor.prototype.constructor=ctor;
}
};
/**
*classfunction.
*/
Returnfunction () {
The last parameter is the new class method, property, and constructor declaration
varsubclazz=arguments[arguments.length-1]| | function () {};
Initialize is a constructor, no constructor is an empty function
Varfn=subclazz.initialize==null?function () {}:subclazz.initialize;
Inherits the class with the most arguments, multiple inheritance, and can also be used as an extension method
for (varindex=0;index<arguments.length-1;index++) {
Inherits (Fn,arguments[index]);
}
Ways to implement new classes
for (Varpropinsubclazz) {
if (prop== "initialize") {
Continue
}
Fn.prototype[prop]=subclazz[prop];
}
RETURNFN;
}
})();
Look at the example below:
Copy Code code as follows:
/**
*thedefinitionofcatclass.
*/
Varcat=class ({
/**
*constructor.
*
* @paramnameCat ' sname
*/
Initialize:function (name) {
This.name=name;
},
/**
*eatfunction.
*/
Eat:function () {
Alert (this.name+ "iseatingfish.");
}
});
/**
*thedefinitionofblackcatclass.
*/
Varblackcat=class (cat,{
/**
*constructor.
*
* @paramnameCat ' sname.
* @paramageCat ' sage.
*/
Initialize:function (name,age) {
Calltheconstructorofsuperclass.
BlackCat.super_.call (This,name);
This.age=age;
},
/**
*eatfunction.
*/
Eat:function () {
Alert (this.name+ "(" +this.age+ ") iseatingdog.");
}
});
/**
*thedefinitionofblackfatcatclass.
*/
Varblackfatcat=class (blackcat,{
/**
*constructor.
*
* @paramnameCat ' sname.
* @paramageCat ' sage.
* @paramweightCat ' sweight.
*/
Initialize:function (name,age,weight) {
Calltheconstructorofsuperclass.
BlackFatCat.super_.call (This,name,age);
This.weight=weight;
},
/**
*eatfunction.
*/
Eat:function () {
Alert (this.name+ "+this.age+") Iseatingdog. Myweight: "+this.weight);
}
});
/**
*thedefinitionofdogclass.
*/
Vardog=class ({});
Varcat=newblackfatcat ("John", "100kg");
Cat.eat ();
True
alert (CATINSTANCEOFCAT);
True
alert (CATINSTANCEOFBLACKCAT);
True
alert (CATINSTANCEOFBLACKFATCAT);
True
alert (CAT.CONSTRUCTOR===BLACKFATCAT);
False
alert (Catinstanceofdog);
Class of MooTools library
Source analysis can be seen here: http://www.cnblogs.com/hmking/archive/2011/09/30/2196504.html
See Specific usage:
A, create a new class
Copy Code code as follows:
Varcat=newclass ({
Initialize:function (name) {
This.name=name;
}
});
Varmycat=newcat (' Micia ');
alert (mycat.name);//alerts ' Micia '
Varcow=newclass ({
Initialize:function () {
Alert (' moooo ');
}
});
b, the implementation of inheritance
Copy Code code as follows:
Varanimal=newclass ({
Initialize:function (age) {
This.age=age;
}
});
Varcat=newclass ({
Extends:animal,
Initialize:function (name,age) {
This.parent (age);//callsinitalizemethodofanimalclass
This.name=name;
}
});
Varmycat=newcat (' Micia ', 20);
alert (mycat.name);//alerts ' Micia '.
alert (mycat.age);//alerts20.
C, the implementation of extended classes
Copy Code code as follows:
Varanimal=newclass ({
Initialize:function (age) {
This.age=age;
}
});
Varcat=newclass ({
Implements:animal,
Setname:function (name) {
This.name=name
}
});
Varmyanimal=newcat (20);
Myanimal.setname (' Micia ');
alert (myanimal.name);//alerts ' Micia '.
v. Understanding through JavaScript: The Nectar of grammar
Take a look at the usage examples first
A, create a class
Copy Code code as follows:
Create a class person
Varperson=class (object,{
Create:function (name,age) {
This.name=name;
This.age=age;
},
Sayhello:function () {
Alert ("Hello,i ' m" +this.name+ "," +this.age+ "yearsold.");
}
});
Varbillgates=new (person,["BillGates", 53]);
Billgates.sayhello ();
B, inheriting class
Copy Code code as follows:
Employee Inherits Person
Varemployee=class (person,{
Create:function (name,age,salary) {
Person.Create.call (This,name,age);
Calling the constructor of a base class
This.salary=salary;
},
Showmethemoney:function () {
Alert (this.name+ "$" +this.salary);
}
});
Varstevejobs=new (employee,["Stevejobs", 53,1234));
Stevejobs.sayhello ();
Stevejobs.showmethemoney ();
Here is the source analysis: Obviously, there is a new method, the creation of classes and new class instances are cleverly encapsulated. form a meaningful whole! There is another point where all classes are based on literals, not on functions. The code is very short, but the principle is very rich and clever, you can savor some!
Copy Code code as follows:
Create a function of a class to declare classes and inheritance relationships
Functionclass (abaseclass,aclassdefine) {
To create a temporary function shell of a class
Functionclass_ () {
This. Type=abaseclass;
We give each class A type attribute that references its inherited class
for (Varmemberinaclassdefine)
This[member]=aclassdefine[member];
Copy all definitions of a class to the currently created class
};
Class_.prototype=abaseclass;
Returnnewclass_ ();
};
Creates a function of an object for object creation of any class
Functionnew (aclass,aparams) {
To create a temporary function shell of an object
Functionnew_ () {
This. Type=aclass;
We also give each object a type attribute that allows access to the class to which the object belongs
if (aclass.create)
AClass.Create.apply (This,aparams);
We agreed that all classes of constructors are called create, which is similar to Delphi
};
New_.prototype=aclass;
Returnnewnew_ ();
};
As the writing is more general, there may be many places did not resolve to, there may be inaccurate places, but also to correct.
Read the above several analytical, believe that they can also write a package of their own library out, as to, how to achieve a person like to see. But the basic thinking is the same as the new method of prototype based inheritance and cyclic copying.
Original from: Mu Yi http://www.cnblogs.com/pigtail/