Creation and inheritance of JS in HTML5 development

Source: Internet
Author: User
Tags ming

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

When we access the properties of an object using Obj.xxx, 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 return undefine D.

For example, create an array object:

var arr = [1, 2, 3];

Its prototype chain is:

ARR----> Array.prototype----> object.prototype----> Null

Array.prototype defines methods such as indexof (), Shift (), so you can call these methods directly on all the array objects.

When we create a function:

function foo () {

return 0;

}

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

Foo----> Function.prototype----> object.prototype----> Null

Because Function.prototype defines methods such as apply (), all functions can call the Apply () method.

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

Except directly with {...} In addition to creating an object, 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.hello = function () {

Alert (' Hello, ' + this.name + '! ');

}

}

You would ask, eh, is this not a normal function?

This is really a normal function, but in JavaScript, you can call this function with the keyword new and return an object:

var xiaoming = new Student (' xiaoming ');

Xiaoming.name; ' Xiao Ming '

Xiaoming.hello (); Hello, Xiaoming!

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

The prototype chain for the newly created Xiaoming is:

Xiaoming----> Student.prototype----> object.prototype----> Null

In other words, Xiaoming's prototype points to the prototype of the function student. If you create Xiaohong and Xiaojun again, the prototypes of these objects are the same as the xiaoming:

Xiaoming

Xiaohong-→student.prototype----> object.prototype----> Null

Xiaojun

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

Xiaoming.constructor = = = Student.prototype.constructor; True

Student.prototype.constructor = = = Student; True

Object.getprototypeof (xiaoming) = = = Student.prototype; True

Xiaoming instanceof Student; True

You look dizzy? Using a graph to show that these messy relationships are:

The red Arrow is the prototype chain. Note that the object that Student.prototype points to is the prototype object of Xiaoming, Xiaohong, and the prototype object has a property constructor of its own, pointing to the Student function itself.

In addition, the function student exactly has a property prototype point to Xiaoming, Xiaohong prototype object, but Xiaoming, xiaohong these objects can not prototype this property, but you can use __proto__ This non-standard usage to view.

Now we think Xiaoming, Xiaohong these objects "inherit" from student.

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

Xiaoming.name; ' Xiao Ming '

Xiaohong.name; ' Little Red '

Xiaoming.hello; Function:Student.hello ()

Xiaohong.hello; Function:Student.hello ()

Xiaoming.hello = = = Xiaohong.hello; False

Xiaoming and Xiaohong have different name, this is right, otherwise we can not distinguish who is who.

Xiaoming and Xiaohong's respective Hello is a function, but they are two different functions, although the function name and code are the same!

If we create a lot of objects with new Student (), the Hello function of these objects actually only needs 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 move the Hello function to Xiaoming, xiaohong these objects common prototype can be, that is student.prototype:

Modify the code as follows:

function Student (name) {

THIS.name = name;

}

Student.prototype.hello = function () {

Alert (' Hello, ' + this.name + '! ');

};

It's so easy to create prototype-based JavaScript objects with new!

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 an error, because this binding is undefined, in non-strict mode, this.name = name does not error, because this binding is window, then inadvertently created global variable name , and returns undefined, the result is even worse.

So, call the constructor and never forget to write new. In order to differentiate 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 checker such as JSLint will help you detect the missing new.

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

function Student (props) {

THIS.name = Props.name | | ' Anonymous '; The default value is ' anonymous '

This.grade = Props.grade | | 1; The default value is 1

}

Student.prototype.hello = function () {

Alert (' Hello, ' + this.name + '! ');

};

function Createstudent (props) {

return new Student (Props | | {})

}

There are several great advantages to this createstudent () function: One is that you do not need new to call, the other is very flexible, you can not pass it, you can pass it like this:

var xiaoming = createstudent ({

Name: ' Xiaoming '

});

Xiaoming.grade; 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 just get an object from JSON, you can create the xiaoming directly.

Inherited

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 constructor:

function Student (props) {

THIS.name = Props.name | | ' Unnamed ';

}

Student.prototype.hello = function () {

Alert (' Hello, ' + this.name + '! ');

}

And student's prototype chain:

Now, to extend the primarystudent based on student, we can first define the primarystudent:

function Primarystudent (props) {

Call the student constructor and bind the This variable:

Student.call (this, props);

This.grade = Props.grade | | 1;

}

However, calling the student constructor does not mean that the prototype that inherits the object created by Student,primarystudent is:

New primarystudent ()----> Primarystudent.prototype----> object.prototype----> Null

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

New primarystudent ()----> Primarystudent.prototype----> Student.prototype----> Object.prototype----> Null

In this way, the prototype chain is right, and the inheritance relationship is right. New Primarystudent-based objects can invoke methods defined by Primarystudent.prototype as well as Student.prototype defined methods.

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 accomplish 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:

function Primarystudent (props) {

Student.call (this, props);

This.grade = Props.grade | | 1;

}

Empty function f:

function F () {

}

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 = new F ();

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:

var xiaoming = new Primarystudent ({

Name: ' Xiaoming ',

Grade:2

});

Xiaoming.name; ' Xiao Ming '

Xiaoming.grade; 2

Validating prototypes:

xiaoming.__proto__ = = = Primarystudent.prototype; True

xiaoming.__proto__.__proto__ = = = Student.prototype; True

To validate an inheritance relationship:

Xiaoming instanceof Primarystudent; True

Xiaoming instanceof Student; True

Use a graph to represent the new prototype chain:

Note that function F is only used for bridging, we have created only a new F () instance, and have not changed the original student definition of the prototype chain.

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

function inherits (Child, Parent) {

var F = function () {};

F.prototype = Parent.prototype;

Child.prototype = new F ();

Child.prototype.constructor = child;

}

This inherits () function can be reused:

function Student (props) {

THIS.name = Props.name | | ' Unnamed ';

}

Student.prototype.hello = function () {

Alert (' Hello, ' + this.name + '! ');

}

function Primarystudent (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:

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

The use of intermediate function f to achieve the prototype chain inheritance, preferably through the encapsulated inherits function to complete;

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

Class inheritance of ES6

The New keyword class was formally introduced into JavaScript from ES6. The purpose of class is to make it easier to define classes.

Let's review the method of implementing student with functions:

function Student (name) {

THIS.name = name;

}

Student.prototype.hello = function () {

Alert (' Hello, ' + this.name + '! ');

}

If you write student with the new class keyword, you can write this:

Class Student {

Constructor (name) {

THIS.name = name;

}

Hello () {

Alert (' Hello, ' + this.name + '! ');

}

}

By comparison, you can see that the definition of class contains the constructor constructor and the function hello () defined on the prototype object (note that there is no function keyword), thus avoiding Student.prototype.hello = function () {...} Such a decentralized code.

Finally, creating a student object code is exactly the same as in the previous chapters:

var xiaoming = new Student (' xiaoming ');

Xiaoming.hello ();

Class inheritance

Another great benefit of defining objects with class is that inheritance is more convenient. Think about the amount of code that we derive from student a primarystudent need to write. Now, the prototype inherits the intermediate object, the prototype object constructor and so on all need not consider, directly through the extends to realize:

Class Primarystudent extends Student {

Constructor (name, grade) {

Super (name); Remember to use Super to call the parent class's constructor Method!

This.grade = grade;

}

Mygrade () {

Alert (' I am at grade ' + This.grade);

}

}

Note that the definition of primarystudent is also implemented by the Class keyword, while extends indicates that the prototype chain object is from student. The constructor for a subclass may not be the same as the parent class, for example, Primarystudent requires the name and grade two arguments, and the constructor of the parent class needs to be called through Super (name), otherwise the parent class's Name property does not initialize properly.

Primarystudent has automatically obtained the Hello method of the parent class student, and we have defined the new Mygrade method in the subclass.

What is the difference between the class introduced by ES6 and the original JavaScript prototype inheritance? In fact, they don't make any difference, and the role of class is to have the JavaScript engine implement the prototype chain code that we originally wanted to write ourselves. In short, the advantage of using class is that it greatly simplifies the prototype chain code.

Source: Qian Feng HTML5

Creation and inheritance of JS in HTML5 development

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.