JavaScript Object-Oriented programming

Source: Internet
Author: User
Tags ming object model

Http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/ 001434499763408e24c210985d34edcabbca944b4239e20000 creating objects with object-oriented programming

JavaScript sets a prototype for each object that is created, pointing to its prototype object.

When we obj.xxx access the properties of an object, the JavaScript engine looks for the property on the current object, and if it is not found, it is found on its prototype object, and if it is not found, it is traced back to the Object.prototype object, and finally, if it is not found, it can only be returned undefined .

For example, create an Array object:

var arr = [1, 2, 3]; // its prototype chain is: NULL

Array.prototypeDefines, and so on, indexOf() shift() so you can Array call these methods directly on all objects.

The function is also an object, and its prototype chain is:

Null

Because Function.prototype apply() such methods are defined, all functions can invoke apply() methods.

It is easy to think that if the prototype chain is long, then accessing an object's properties will become slower because it takes more time to find it, so be careful not to make the prototype chain too long.

constructor function

In addition to { ... } creating an object directly, JavaScript can also create objects using a constructor method. The use of it is to define a constructor first:

function Student (name) {    this. Name = name;       This function () {        alert (this. Name + '! ') );    }}

Like a normal function, but in JavaScript, you can new call this function with a keyword and return an object:

var New Student (' Xiao Ming'//  ' Xiao Ming '//  Hello, Xiaoming!

Note that if you do not write new , this is a normal function that returns undefined . However, if new it is written, it becomes a constructor that binds to the this newly created object and returns it by default this , that is, it does not need to be written at the last point return this; .

The newly created xiaoming prototype chain is:

Null

In other words, xiaoming the prototype points to Student the prototype of the function. If you create again, xiaohong the xiaojun prototypes of these objects xiaoming are the same:

xiaoming Xiaohong-→student.prototype----> object.prototype---->nullXiaojun  

new Student()the created object also obtains a property from the prototype constructor , which points to the function Student itself:

// true // true // true instanceof // true

Using a graph to show that these messy relationships are:

The red Arrow is the prototype chain. Notice that the Student.prototype object that is pointing to is the xiaoming xiaohong prototype object, and the prototype object itself has a property constructor that points to the Student function itself.

In addition, the function Student has exactly prototype a xiaoming prototype object pointing to the property, xiaohong but xiaoming xiaohong these objects may not have prototype this property, but can be __proto__ viewed in this non-standard usage.

Now we think that xiaoming xiaohong these objects are "inherited" from Student .

However, there is a small problem, pay attention to observation:

// ' Xiao Ming ' // ' Little Red ' // Function:Student.hello () // Function:Student.hello () // false

xiaomingIt's right to be xiaohong different from each name other, otherwise we can't tell who is who.

xiaomingand xiaohong each hello is a function, but they are two different functions, although the function name and code are the same!

If we new Student() create a lot of objects, the functions of these objects hello actually only need to share the same function, which can save a lot of memory.

To let the created object share a hello function, according to the object's property lookup principle, we just hello move the function to the xiaoming xiaohong Common prototype of these objects, that is Student.prototype :

Modify the code as follows:

function Student (name) {    this.name =function  () {    alert (this . Name + '! ' );};

It's new so easy to create a prototype-based JavaScript Object!

Forget to write new what to do

What if a function is defined as the constructor used to create the object, but when the call forgets to write new ?

In strict mode, this.name = name will be error, because the this binding is undefined , in the non-strict mode, this.name = name no error, because the this binding is window , then inadvertently created a global variable name , and return undefined , this result is worse.

So, call the constructor and never forget to write new . In order to distinguish between ordinary functions and constructors, by convention, the initial letter of the constructor should be capitalized, and the first letter of the ordinary function should be lowercase, so that some grammar checking tools such as JSLint will be able to help you detect the missing write new .

Finally, we can also write a createStudent() function that encapsulates all the operations internally new . A common programming pattern is like this:

 function   Student (props) { this . Name = Props.name | | ' Anonymous '; //     this . Grade = Props.grade | | 1; //  }student.prototype.hello  = function  Span style= "color: #000000;" () {alert ( ' Hello, ' +   function   Createstudent (props) {  return  new  Student (Props | |  

This createStudent() function has several great advantages: one is not required new to call, the other is very flexible parameters, can not pass, can also be transmitted:

var xiaoming = createstudent ({name: ' xiaoming '//  1

If you create an object that has many properties, we only need to pass some of the required properties, and the rest of the properties can be used as default values. Since the parameter is an object, we do not need to memorize the order of the parameters. If you happen JSON to get an object from it, you can create it directly xiaoming .

Prototype inheritance

In traditional class-based languages such as Java and C + +, the essence of inheritance is to extend an existing class and generate new subclass.

Because such languages strictly differentiate between classes and instances, inheritance is actually an extension of the type. However, because of the prototype inheritance of JavaScript, we cannot extend a class directly because there is no such type as class.

But there are some ways. Let's review the Student constructors first:

function Student (props) {    this. Name = Props.name | | ' Unnamed 'function  () {    alert (this. Name + '! ') );}

and Student the prototype chain:

Now, based on the Student extension PrimaryStudent , we can first define PrimaryStudent :

function primarystudent (props) {    //  Call Student constructor, bind this variable:    student.call (This , props);     this. Grade = Props.grade | | 1;}

However, the constructor that was called Student does not equal inheritance Student , and the prototype of the PrimaryStudent created object is:

New NULL

We must find a way to modify the prototype chain to:

New NULL

In this way, the prototype chain is right, and the inheritance relationship is right. The new creation-based PrimaryStudent object can invoke not only the PrimaryStudent.prototype defined method, but also Student.prototype the defined method.

If you want to do this in the simplest and most brutal way:

Primarystudent.prototype = Student.prototype;

It's not going to work! If so, PrimaryStudent and Student share a prototype object, what do you define PrimaryStudent ?

We must use an intermediate object to achieve the correct prototype chain, the prototype of this intermediate object to point to Student.prototype . To achieve this, refer to the Code of the Master (that is, the Douglas that invented JSON), which can be implemented with an empty function F :

//Primarystudent Constructor:functionprimarystudent (props) {Student.call ( This, props);  This. grade = Props.grade | | 1;}//empty function f:functionF () {}//point the prototype F to Student.prototype:F.prototype =Student.prototype;//to point the Primarystudent prototype to a new F object, the prototype of the F object points to Student.prototype:Primarystudent.prototype =NewF ();//Fix the Primarystudent prototype constructor to Primarystudent:PrimaryStudent.prototype.constructor =primarystudent;//continue to define the method on the Primarystudent prototype (that is, the new F () object):PrimaryStudent.prototype.getGrade =function () {    return  This. grade;};//Create Xiaoming:varXiaoming =Newprimarystudent ({name:' Xiao Ming ', Grade:2}); xiaoming.name; //' Xiao Ming 'Xiaoming.grade;//2//Validating prototypes:xiaoming.__proto__ = = = Primarystudent.prototype;//truexiaoming.__proto__.__proto__ = = = Student.prototype;//true//To validate an inheritance relationship:XiaominginstanceofPrimarystudent;//trueXiaominginstanceofStudent;//true

Use a graph to represent the new prototype chain:

Note that the function is F only for bridging, we have created only one new F() instance, and there is no Student prototype chain that changes the original definition.

If you enclose the inherited action in a inherits() function, you can also hide F the definition and simplify the code:

function inherits (Child, Parent) {    varfunction  () {};     = Parent.prototype;     New F ();     = Child ;}

This inherits() function can be reused:

functionStudent (props) { This. Name = Props.name | | ' Unnamed ';} Student.prototype.hello=function() {alert (' Hello, ' + This. Name + '! ');}functionprimarystudent (props) {Student.call ( This, props);  This. grade = Props.grade | | 1;}//To implement a prototype inheritance chain:inherits (Primarystudent, Student);//to bind other methods to the Primarystudent prototype:PrimaryStudent.prototype.getGrade =function () {    return  This. grade;};
Summary

JavaScript's prototype inheritance is implemented in the following way:

    1. Define a new constructor, and internally call() invoke the constructor that you want to "inherit" and bind to it this ;

    2. Fthrough the intermediate function to realize the prototype chain inheritance, it is best to complete the encapsulated inherits function;

    3. Continue to define new methods on the prototype of the new constructor.

Class inheritance

In the above chapters we see the JavaScript object model is based on the prototype implementation, the feature is simple, the disadvantage is more difficult to understand than the traditional class-instance model, the biggest disadvantage is that the implementation of the inheritance needs to write a large number of code, and the need to correctly implement the prototype chain.

New keywords class are formally introduced into JavaScript from ES6. classThe goal is to make it easier to define classes.

Let's review the methods implemented with functions Student :

function Student (name) {    this. Name =function  () {    alert (this). Name + '! ' );}

If you write with a new class keyword Student , you can write it like this:

class Student {    constructor (name) {        this. Name= name;    }    Hello () {        alert (this. Name + '! ') );    }}

By comparison, you can see that class the definition contains constructors constructor and functions defined on the prototype object hello() (note that there are no function keywords), thus avoiding Student.prototype.hello = function () {...} such scattered code.

Finally, creating an Student object code is exactly the same as the previous chapter:

var New Student (' Xiao Ming '); Xiaoming.hello ();
Class inheritance

classanother great benefit of defining an object is that inheritance is more convenient. Think about Student PrimaryStudent The amount of code we derive from a need to write. Now, the prototype inherits the intermediate object, the prototype object constructor and so on all need not consider, directly through extends to realize:

class Primarystudent extends Student {    constructor (name, grade) {        //  Remember to call the constructor of the parent class with Super! this        . grade = grade;    }    Mygrade () {        alert (this. grade);    }}

Note that PrimaryStudent the definition is also implemented by the Class keyword, which means that the extends prototype chain object comes from Student . The constructor for a subclass may not be the same as the parent class, for example, PrimaryStudent requires name and grade two arguments, and you need to super(name) invoke the constructor of the parent class, otherwise the properties of the parent class are name not initialized properly.

PrimaryStudentThe method of the parent class has been automatically obtained Student hello , and we have defined the new method in the subclass myGrade .

classWhat is the difference between the ES6 introduced and the original JavaScript prototype inheritance? In fact, they do not make any difference, class the role is to let the JavaScript engine to achieve the original need to write our own prototype chain code. In short, class the advantage is that the prototype chain code is greatly simplified.

You must ask, class so good, can you use it now?

It's a little early because not all mainstream browsers support ES6 's class. If you must use it now, you need a tool to class convert the code into traditional prototype code, and you can try Babel the tool.

JavaScript Object-Oriented programming

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.