JS Object-Oriented Programming details, js Object-Oriented Programming
Preface
In the big world of JavaScript, we need to discuss object-oriented. Two points should be mentioned: 1. JavaScript is a prototype-based object-oriented language. 2. It simulates object-oriented languages. For the reason why we need to simulate object-oriented language, I personally think: in some cases, prototype can provide some convenience, but in complex applications, the prototype-based object-oriented system is unsatisfactory in abstraction and inheritance. JavaScript is the only scripting language supported by various browsers, so various experts have to use various methods to improve the convenience of the language, the result of optimization is that the Code it writes is more and more like the object-oriented method in the class language, which also masks the essence of the JavaScript prototype system.
Prototype-based object-oriented language
Like the class mode, the prototype mode is a programming generic model, that is, the programming methodology. In addition, function programming is also a programming generic model. Brendan Eich, the father of JavaScript, did not intend to add the class concept to JavaScript from the very beginning. Instead, he borrowed two prototype-based languages: Self and Smalltalk.
Since it is also an object-oriented language, there must be a method for creating objects. In a class language, an object is created based on a template. First, a class is defined as an abstraction of the real world, and then an object is instantiated by the class. In a prototype language, an object is created by cloning another object. The cloned parent object is called a prototype object.
The key to cloning is whether the language itself provides us with native cloning methods. In ECMAScript5, Object. create can be used to clone objects.
var person = { name: "tree", age: 25, say: function(){ console.log("I'm tree.") }};var cloneTree = Object.create(person);console.log(cloneTree);
The purpose of the prototype mode is not to get an identical object, but to provide a convenient way to create an object (from JavaScript design mode and development practices). However, due to language design problems, there are many contradictions in the JavaScript prototype. Some of its complex syntaxes seem to be those class-based languages, these Syntax problems cover up its prototype mechanism (from the essence of JavaScript). For example:
function Person(name, age){ this.name = name; this.age = age; }var p = new Person('tree', 25)
In fact, when a Function object is created, the Function object generated by the Function constructor runs code similar to the following:
this.prototype = {constructor: this}
The new function object is assigned a prototype attribute. Its value is an object that contains the constructor attribute and its attribute value is the new function. When the new operator is used for a function, the value of the prototype attribute of the function is used as the prototype object to clone the new object. If the new operator is a method, the execution process is as follows:
Function. prorotype. new = function () {// use the prototype attribute value as the prototype Object to clone a new Object var that = Object. create (this. prorotype); // In the function, this indicates that the new cloned object var other = this. apply (that, arguments); // If the returned value is not an object, return the new cloned object return (other & typeof other = 'object ')? Other: that ;}
It can be seen from the above that although calling a function using the new operator looks like creating an object using template instantiation, the new object is basically cloned using a prototype object.
Since the new cloned object can access all the methods and attributes of the prototype object, coupled with the features of the new operator, this has become the cornerstone of using the prototype simulation language.
Use prototype simulation language
Abstraction
Classes are simulated in prototype mode. First, classes are abstracted. According to the characteristics of the JavaScript language, a class (actually a pseudo class) usually places a field in the constructor (actually a function called by the new operator, javaScript itself does not have the concept of constructor), and the method is placed in the prototype attribute of the function.
function Person(name, age) { this.name = name; this.age = age;};Person.prototype.say = function(){ console.log("Hello, I'm " + this.name);};
Inheritance
Inheritance is one of the most talked-about concepts in OO language. Many OO languages support two inheritance Methods: interface inheritance and implementation inheritance. Interfaces inherit the method signature, while implementing inheritance inherits the actual method. However, in ECMAScript, interface inheritance cannot be implemented, but only implementation inheritance is supported, and its implementation inheritance mainly relies on the prototype chain. (From section 6.3 of JavaScript advanced programming-inheritance) the authors of November 3 explored various inheritance simulations, such as combination inheritance, prototype inheritance, parasitic inheritance, and parasitic combination inheritance, finally, the parasitic components form the basis for all simulated class inheritance.
function Person(name, age) { this.name = name; this.age = age;};Person.prototype.say = function(){ console.log("Hello, I'm " + this.name);};function Employee(name, age, major) { Person.apply(this, arguments); this.major = major;};Employee.prototype = Object.create(Person.prototype);Employee.prorotype.constructor = Employee;Employee.prorotype.sayMajor = function(){ console.log(this.major);}
In the third year, only the single inheritance solution is provided. We have to find a solution for simulating multi-inheritance. Because multi-inheritance has its own difficulties: If the object-oriented language supports multi-inheritance, it will encounter the famous Diamond Problem ). Suppose there is an inheritance relationship as shown in the left figure. In O, there is A method foo, Which is overwritten by Class A and Class B, but not by Class C. So when C calls the foo method, will it call foo in a or foo in B?
Therefore, most languages do not support multi-inheritance. For example, Java supports the form of single inheritance + interface. JavaScript does not support interfaces. What should I do if I want to simulate interfaces in a language that does not support interfaces? The answer is the famous duck-style model. In actual code, it is mixed into (mixin ). The principle is simple:
function mixin(t, s) { for (var p in s) { t[p] = s[p]; } }
It is worth mentioning that dojo uses MRO (Method Resolution Order) to solve the problem of multi-inheritance.
At this point, we have understood the basic principles of the simulation language. As a tossing programmer, I want to simplify the creation of classes in my own way:
- Provides a convenient way to create a class without exposing the prototype attribute of the function.
- When a subclass overwrites the parent class method, the super function can be provided like Java to directly access the method with the same name as the parent class.
- Add static variables and methods in a more convenient way without worrying about prototype.
- Support Attribute like C #
Finally, I wrote my own class creation tool O. js based on the knowledge of all the experts:
(Function (global) {var define = global. define; if (define & define. amd) {define ([], function () {return O ;});} else {global. O = O ;}function O () {}; O. derive = function (sub) {debugger; var parent = this; sub = sub? Sub :{}; var o = create (parent); var ctor = sub. constructor | function () {}; // how to call the constructor of the parent class? Var statics = sub. statics | {}; var MS = sub. mixins | []; var attrs = sub. attributes | {}; delete sub. constructor; delete sub. mixins; delete sub. statics; delete sub. attributes; // process the inheritance ctor. prototype = o; ctor. prototype. constructor = ctor; ctor. superClass = parent; // use the DefineProperties method to process Attributes // for (var p in attrs) {Object. defineProperties (ctor. prototype, attrs); // static attribute mixin (ctor, statics); // mix other attributes and methods, note that the attribute here is the mixin (ctor. prototype, sub); // simulate multi-inheritance for (var I = 0, len = ms. length; I <len; I ++) {mixin (ctor. prototype, MS [I] | |{});} ctor. derive = parent. derive; // _ super function ctor. prototype. _ super = function (f) {debugger; return parent. prototype [f]. apply (this, Array. prototype. slice. call (arguments, 1);} return ctor;} function create (clazz) {var F = function () {}; F. prototype = clazz. prototype; // F. prototype. constructor = F; // return new F () ;}; function mixin (t, s) {for (var p in s) {t [p] = s [p] ;}}) (window );
Class creation method:
Var Person = O. derive ({constructor: function (name) {// constructor this. setInfo (name) ;}, statics: {// static variable declaredClass: "Person"}, attributes: {// simulate the attribute Name: {set: function (n) in C) {this. name = n; console. log (this. name) ;}, get: function () {return this. name + "Attribute" ;}}, share: "asdsaf", // The variable is located on the prototype object, and the setInfo: function (name) {// method this is used for all objects. name = name ;}}); var p = new Person ('lzz '); console. log (p. name); // lzzAttributeconsole. log (Person );
Inheritance:
Var Employee = Person. derive ({// subclass has a parent class derived from constructor: function (name, age) {this. setInfo (name, age) ;}, statics: {declaredClass: "Employee"}, setInfo: function (name, age) {this. _ super ('setinfo', name); // call the method of the same name as the parent class this. age = age ;}}); var e = new Employee ('lll', 25); console. log (e. name); // lllAttributeconsole. log (Employee );
The above is all the content of this article, hoping to help you learn.
Articles you may be interested in:
- Object Usage Analysis of JS Object-Oriented Programming
- Object-oriented Javascript 2 (interface implementation)
- Javascript object-oriented (1) (common methods, private methods, privileged methods)
- JavaScript object-oriented Prototypes and inheritance
- Basic Introduction to javascript object-oriented
- Analysis of Class encapsulation Class libraries for javascript object-oriented Packaging
- Js general method rewrite to object-oriented method infinite folding menu sample code
- Getting started with JavaScript Object-Oriented Programming
- JS object-oriented basic explanation (factory mode, constructor mode, prototype mode, hybrid mode, dynamic prototype mode)