Home > Web Front-end > JS Tutorial > Detailed explanation of JavaScript prototype and inheritance examples

Detailed explanation of JavaScript prototype and inheritance examples

零下一度
Release: 2017-06-26 10:55:54
Original
1032 people have browsed it

Prototype chain

Every object in JavaScript has a built-in _proto_ attribute. This attribute is invisible to programming. It is actually a function of the other objects. An object or a reference to null.

#When an object references an attribute, the JavaScript engine will first search it from the object's own attribute table. If found, it will perform corresponding read and write operations. If it is not found in its own attribute table, search in the attribute table of the object referenced by the _proto_ attribute, and so on until this attribute or _proto_ is found. The attribute points to null.

The reference chain of _proto_ is called the prototype chain .

Note that there is a performance optimization problem here: the deeper you search in the prototype chain, the more time it takes.

Prototype chain and constructor

JavaScript is an object-oriented language and can Prototypal inheritance.

The function in JavaScript has an attribute prototype, this prototype attribute is an object, one of its attributes constructorReferences the function itself. That is:

 func.prototype.constructor === func; // ==> true
Copy after login

What is the use of this attribute? We know that when a function is called using the new operator, it will return a new object as a constructor. The _proto_ property of this object refers to the prototype property of its constructor.

So this is not difficult to understand:

var obj = new Func();

obj.constructor == Func; // ==> true
Copy after login

There is also this:

obj instanceof Func; // ==> true
Copy after login

It is also by looking up the prototype chain Implemented by the constructor attribute.

The _proto_ attributes of different instances generated by the constructor are references to the same prototype object. So modifying the prototype object will affect all instances.

Several ways of "subclass" inheritance implementation

The reason why subclasses need to be quoted is because the concept of "class" is not rigorous here. JavaScript is an object-oriented language, but unlike Java and other languages, it does not have class definitions before the ES6 standard is released.

But programmers who are familiar with languages ​​​​such as Java also hope that when using JavaScript, they can generate instances through classes and reuse code through subclasses, similar to using Java. So before ES6, how to use a "class"-like method like the following code?

var parent = new Parent("Sam");var child = new Children("Samson");

parent.say(); // ==> "Hello, Sam!"child.say(); // ==> "Hello, Samson! hoo~~"child instanceof Parent; // ==> true
Copy after login

We see that here we use the constructor as a class.

Let’s discuss several ways to implement it:

The simplest way

Combined with the concept of prototype chain, we can easily write such code:

function Parent(name){this.name = name;
}

Parent.prototype.say = function(){
    console.log("Hello, " + this.name + "!");
}function Children(name){this.name = name;
}

Children.prototype = new Parent();

Children.prototype.say = function(){
    console.log("Hello, " + this.name + "! hoo~~");
}
Copy after login

The disadvantage of this method is obvious: as a constructor of a subclass, it needs to rely on an object of the parent class. The properties name in this object are completely useless.

First improvement

// ...Children.prototype = Parent.prototype;// ...
Copy after login

So that useless parent class attributes will not be generated.

However, in this case, the prototypes of the subclass and the parent class refer to the same object, and modifying the prototype of the subclass will also affect the prototype of the parent class.

At this time we discovered:

parent.say(); // ==> "Hello,Sam! hoo~~"
Copy after login

This first improvement is worse than no change at all.

The second improvement - temporary constructor/Object.create()

function F(){  // empty  }

F.prototype = Parent.prototype;

Children.prototype = new F();// ...parent.say(); // ==> "Hello, Sam!"child.say();  // ==> "Hello, Samson! hoo~~"
Copy after login

In this way, modifying the prototype of the subclass is just Modified the properties of a instance of F without changing Parent.prototype, thus solving the above problem.

In the era of ES5, we can also do this directly:

Children.prototype = Object.create(Parent.prototype);
Copy after login

这里的思路是一样的,都是让子类的prototype不直接引用父类prototype。目前的现代浏览器几乎已经添加了对这个方法的支持。(但我们下面会仍以临时构造函数为基础)

但是细细思考,这个方案仍有需要优化的地方。例如:如何让父类的构造函数逻辑直接运用到子类中,而不是再重新写一遍一样的?这个例子中只有一个name属性的初始化,那么假设有很多属性且逻辑一样的话,岂不是没有做到代码重用?

第三次改进——构造函数方法借用

使用apply/call,实现“方法重用”的思想。

function Children(name){
    Parent.apply(this, arguments);// do other initial things}
Copy after login

“圣杯”模式

现在完整的代码如下:

function Parent(name){this.name = name;
}

Parent.prototype.say = function(){
    console.log("Hello, " + this.name + "!");
}function Children(name){
    Parent.apply(this, arguments);// do other initial things}function F(){  // empty  }

F.prototype = Parent.prototype;

Child.prototype = new F();

Children.prototype.say = function(){
    console.log("Hello, " + this.name + "! hoo~~");
}
Copy after login

这就是所谓“圣杯”模式,听着很高大上吧?

以上就是ES3的时代,我们用来实现原型继承的一个近似最佳实践。

“圣杯”模式的问题

“圣杯”模式依然存在一个问题:虽然父类和子类实例的继承的prototype对象不是同一个实例,但是这两个prototype对象上面的属性引用了同样的对象。

假设我们有:

Parent.prototype.a = { x: 1};// ...
Copy after login

那么即使是“圣杯”模式下,依然会有这样的问题:

parent.x // ==> 1child.x  // ==> 1child.x = 2;
parent.x // ==>2
Copy after login

问题在于,JavaScript的拷贝不是 深拷贝(deepclone)

要解决这个问题,我们可以利用属性递归遍历,自己实现一个深拷贝的方法。这个方法在这里我就不写了。

ES6

ES6极大的支持了工程化,它的标准让浏览器内部实现类和类的继承:

class Parent {
    constructor(name) { //构造函数  this.name = name;
    }
    say() {
          console.log("Hello, " + this.name + "!");
    }
}

class Children extends Parent {
    constructor(name) { //构造函数super(name);    //调用父类构造函数// ...    }
    say() {
          console.log("Hello, " + this.name + "! hoo~~");
    }
}
Copy after login

从此走上强类型的不归路。。。

上张顿悟图

什么?还不明白?!麻烦出门左拐。推荐阮老师JavaScript万物诞生记。 

The above is the detailed content of Detailed explanation of JavaScript prototype and inheritance examples. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template