Implementations that are inherited in JavaScript

Source: Internet
Author: User

Unlike class-based programming languages such as C + + and Java,javascript, inheritance is based on prototypes. And because JavaScript is a very flexible language, there are many ways to implement inheritance.

The primary basic concept is about constructors and prototype chains, where the constructor of the parent object is called, Parent and the child object's constructor is called Child , and the corresponding parent object and child object are respectively parent child .

Object has a hidden property [[prototype]] (note not prototype ), is in Chrome __proto__ , and in some circumstances is inaccessible, it points to the object's prototype. When a property or method of any object is accessed, all properties of the object are searched first, and if not found, the [[prototype]] properties on its prototype object are searched incrementally along the prototype chain until it is found, otherwise it is returned undefined .

Prototype chain inheritance

The prototype chain is the default way to implement inheritance in JavaScript, and the simplest way to make child objects inherit from a parent object is to point the property of the child object constructor to prototype an instance of the parent object:

function Parent() {}function Child() {}Child.prototype = new Parent()

This time, Child the prototype property is rewritten, pointing to a new object, but the property of the new object constructor is not pointing correctly Child , the JS engine does not automatically do the work for us, which requires us to manually go to Child the prototype object's constructor properties to point back to Child:

Child.prototype.constructor = Child

The above is the default inheritance mechanism in JavaScript, migrating properties and methods that need to be reused into prototype objects, and setting the non-reusable part as the object's own property, but this inheritance requires a new instance as a prototype object, which is less efficient.

Prototype inheritance (non-prototype chain)

To avoid the problem of duplicating the creation of a prototype object instance on the previous method, you can direct the child object constructor to the prototype parent object constructor, prototype so that all Parent.prototype properties and methods can be reused without having to recreate the prototype object instance:

Child.prototype = Parent.prototypeChild.prototype.constructor = Child

But we know that in JavaScript, the object is present as a reference type, and this method actually points to the Child.prototype Parent.prototype same object as the pointer being saved, so when we want to extend some properties in the child object prototype to continue inheriting later, The prototype of the parent object is also overwritten because there is always only one instance of the prototype object here, which is also a disadvantage of this inheritance method.

Temporary constructor inheritance

To solve the above problem, you can borrow a temporary constructor that acts as a middle tier, and all child object prototypes are done on an instance of the temporary constructor without affecting the parent object prototype:

var F = function() {}F.prototype = Parent.prototypeChild.prototype = new F()Child.prototype.constructor = Child

Also, in order to access the properties in the parent prototype in the child object, you can include a property on the child object constructor that points to the parent object's prototype, such that uber you can child.constructor.uber access the parent prototype object directly on the child object.

We can encapsulate the above work into a function that can be easily implemented by invoking this function later:

function extend(Child, Parent) {    var F = function() {} F.prototype = Parent.prototype Child.prototype = new F() Child.prototype.constructor = Child Child.uber = Parent.prototype}

You can then invoke this:

extend(Dog, Animal)
Property Copy

This inheritance basically does not change the relationship of the prototype chain, but rather directly copies the properties of the parent prototype object into the child object prototype, of course, the copy here only applies to the basic data type, the object type only supports reference delivery.

function extend2(Child, Parent) {    var p = Parent.prototype var c = Child.prototype for (var i in p) { c[i] = p[i] } c.uber = p}

In this way, some of the prototype properties are reconstructed and the object is less efficient to construct, but it can reduce the search for the prototype chain. But I personally think the advantages of this approach are not obvious.

Inter-Object inheritance

In addition to the constructor-based inheritance method, you can also leave the constructor to inherit directly between objects. This is a direct copy of the object's properties, including shallow and deep copies.

Shallow copy

Accept the object you want to inherit, create a new empty object, copy the properties of the inherited object to the new object, and return the new object:

function extendCopy(p) {    var c = {} for (var i in p) { c[i] = p[i] } c.uber = p return c}

After the copy is complete, you can manually overwrite the properties that need to be overwritten in the new object.

Deep copy

A shallow copy of the problem is also obvious, it can not copy the properties of the object type and can only pass the reference, to solve the problem is to use a deep copy. The deep copy focuses on the recursive invocation of the copy, creating the corresponding object or array when the properties of the object type are detected, and copying the underlying type values in one.

function deepCopy(p, c) {    c = c || {}    for (var i in p) { if (p.hasOwnProperty(i)) { if (typeof p[i] === ‘object‘) { c[i] = Array.isArray(p[i]) ? [] : {} deepCopy(p[i], c[i]) } else { c[i] = p[i] } } } return c}

A ES5 Array.isArray() method is used to determine if the parameter is an array, and an environment that does not implement this method requires you to manually encapsulate a shim.

Array.isArray = function(p) {    return p instanceof Array}

However, it is instanceof not possible to use operators to judge array variables from different frameworks, but this is less.

Prototype inheritance

With the parent object, a new object is created with the parent object as a prototype through the constructor:

function object(o) {    var n function F() {} F.prototype = o n = new F() n.uber = o return n}

Here, the parent object is set directly to the prototype of the child object, and the method in ES5 Object.create() is the way it is implemented.

Prototype inheritance and attribute copy blending

In the prototype inheritance method, the child object is built as a prototype of the passed-in parent, and you can also pass in additional objects that require copying properties beyond the properties provided by the parent object:

function ojbectPlus(o, stuff) {    var n function F() {} F.prototype = o n = new F() n.uber = o for (var i in stuff) { n[i] = stuff[i] } return n}
Multiple inheritance

This approach does not involve the operation of the prototype chain, passing in multiple objects that require a copy of the property, followed by a full copy of the attribute:

function multi() {    var n = {}, stuff, i = 0, len = arguments.length for (i = 0; i < len; i++) { stuff = arguments[i] for (var key in stuff) { n[i] = stuff[i] } } return n}

Copies are copied sequentially based on the order in which the objects are passed in, that is, if the subsequent incoming object contains the same properties as the previous object, the latter overrides the former.

Constructor borrowing

JavaScript call() and methods are apply() very useful, and the ability to change the execution context of a method can also work in an inherited implementation. The so-called constructor borrowing refers to the operation of borrowing the parent object's constructor in the child object builder this :

function Parent() {}Parent.prototype.name = ‘parent‘function Child() { Parent.apply(this, arguments)}var child = new Child()console.log(child.name)

The great advantage of this approach is that in the constructor of a child object, it is a complete rebuild of its own property, and a variable of the reference type will generate a new value instead of a reference, so any manipulation of a child object will not affect the parent object.

The disadvantage of this approach is that the operator is not used during the construction of the child object, new so the child object does not inherit any properties on the parent prototype object, and in the above code, child the name property will be undefined .

To resolve this problem, you can manually set the child object constructor prototype to an instance of the parent object again:

new Parent()

However, this brings another problem, that is, the constructor of the parent object is called two times, one time in the parent object constructor borrowing, and the other during the inheritance prototype process.

To solve this problem, we need to remove the call of the parent object constructor, the constructor borrowing cannot be omitted, then the next call can only be removed, and another way to implement the inherited prototype is to iterate the replication:

extend2(Child, Parent)

Use the extend2() method you implemented earlier.

Implementations that are inherited in JavaScript

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.