Home > Web Front-end > JS Tutorial > body text

A brief analysis of JavaScript inheritance and prototype chain

WBOY
Release: 2022-02-15 17:45:29
forward
2071 people have browsed it

This article brings you knowledge about inheritance and prototype chain in javascript, including issues related to constructors, prototypes and class syntax sugar. I hope it will be helpful to everyone.

A brief analysis of JavaScript inheritance and prototype chain

A brief analysis of inheritance and prototype chain of JavaScript

1. Preface

Inheritance and prototype chain of JavaScript It is a rare and difficult-to-understand part that I encountered in the process of learning front-end. Here I have recorded everything I know and learned. I hope it can give some tips to brothers who are still struggling in this. Please help me, and you are also welcome to criticize and correct me.

2. Constructor

2.1 Instance members and static members of the constructor

The constructor consists of both instance members and static members, where Instance members are members added inside the function through the this keyword; they can only be accessed through the instantiated object later; while static members are members added to the function itself and can only be accessed through the constructor Come visit.

//创造一个构造函数let Father = function(name,age){
    //实例成员
    this.name = name;
    this.age = age;
    this.method = "我是一个实例成员";}
    //静态成员Father.like = "mother";
    //检验实例对象是否能够被构造函数直接访问console.log(Father.method);
    //undefinedconsole.log(Father.like);
    //mother
    //实例化一个对象let father = new Father("小王",27);
    //检验静态对象是否能够被实例化对象访问console.log(father.name);
    //小王console.log(father.age);
    //27console.log(father.like);
    //undefined
Copy after login

2.2 The process of instantiating an object

You can implement an instantiated object through the constructor through the new keyword, so what happens during the specific instantiation process? Woolen cloth? It can be roughly divided into the following steps:

(1) Create an empty object son {}

(2) Prepare a prototype chain connection for son son.__proto__ = Father.prototype

(3) Rebind this so that this of the constructor points to the new object Father.call(this)

(4) As the new object attribute Assignment son.name

(5) Return this return this. At this time, the new object will have the methods and properties of the constructor

A small question: Are all methods of instantiating objects shared?

There are two methods of constructing functions. The first is the method directly defined inside the function, and the second is the method added through the prototype;

//函数内部直接定义的方法let Father = function(){
    this.read = function(){
        console.log("我是内部定义的read方法!");
    }}//通过A brief analysis of JavaScript inheritance and prototype chain添加的方法Father.prototype.look = function(){
    console.log("我是通过A brief analysis of JavaScript inheritance and prototype chain定义的look方法!");}
    //实例化对象进行检验let father1 = new Father();let father2 = new Father();
    father1.read();
    //我是内部定义的read方法!father2.read();
    //我是内部定义的read方法!console.log(father1.read === father2.read);
    //falsefather1.look();
    //我是通过A brief analysis of JavaScript inheritance and prototype chain定义的look方法!father2.look();
    //我是通过A brief analysis of JavaScript inheritance and prototype chain定义的look方法!console.log(father1.look === father2.look);
    /true
Copy after login

It can be found that directly inside the function Every time a new object is instantiated for a defined method, a new memory space will be allocated to this method, and methods added through the prototype will share the same space.

A small question: Are the properties of all instantiated objects shared?

There is no problem of memory space. When judging, it depends on whether the values ​​are the same;

let Father = function(name){
    this.name = name;}let father1 = new Father("小王");
    let father2 = new Father("小红");
    console.log(father1.name === father2.name);
    //falselet father1 = new Father("小王");
    let father2 = new Father("小王");
    console.log(father1.name === father2.name);
    //true
Copy after login

So we can summarize the basic rules for defining constructors, that is, public attributes are defined to the constructor Inside, we put the public methods on the prototype object.

3. Prototype

3.1 What is a prototype

Father.prototype is a prototype. It is an object and can also be called a prototype. object.

3.2 What is the role of prototype

The role of prototype is to share methods.

We can share methods through Father.prototype.method, which will not reflect the space storage method.

3.3 Where does this in the prototype point to?

The point of this in the prototype is the instance.

4. Prototype Chain

I feel that the prototype chain is something that is particularly difficult to understand for beginners or some front-end noobs (such as myself). In order to make the following parts easier to understand, it is mandatory to remember the following points here:

  1. __proto__ is an attribute that every object has, and prototype is unique to each function. Method;
  2. The __proto__ attribute of each object will point to the prototype of its own constructor;
  3. The constructor attribute always points to the constructor that created the current object;
  4. Function.__proto__ === Function.prototype;
  5. Object.prototype.__proto__ === null is the end point of the prototype chain;

4.1 What is the prototype chain

The process of linking prototypes layer by layer is the prototype chain.

4.2 Application of prototype chain

Objects can use the properties and methods of the constructor prototype prototype object, because the object has __proto__The existence of the prototype is # for each object ##__proto__Existence of prototype

let Father = function(name){
    this.name = name;}let father = new Father("老王");console.log(father.__proto__ === Father.prototype);
    //true
    //验证上述说法中的第二条
Copy after login
4.3 Prototype chain diagram

A brief analysis of JavaScript inheritance and prototype chain

Combined with the points written at the top, there should be no problem in understanding the above diagram It's bigger, and the circled part in the picture is the appalling prototype chain.

4.4 How to search the prototype chain

function Star(name) {
	this.name = name;
	//(1)首先看obj对象身上是否有dance方法,如果有,则执行对象身上的方法
	this.dance = function () {
		console.log(this.name + '1');
	}}//(2)如果没有dance方法,就去构造函数原型对象prototype身上去查找dance这个方法。Star.prototype.dance = function () {
	console.log(this.name + '2');};
	//(3)如果再没有dance方法,就去Object原型对象prototype身上去查找dance这个方法。Object.prototype.dance = function () {
	console.log(this.name + '3');};
	//(4)如果再没有,则会报错。let obj = new Star('小红');obj.dance();
Copy after login

(1) First check whether there is a dance method on the obj object. If so, execute the method on the object.

(2) If there is no dance method, go to the constructor prototype object prototype to find the dance method.

(3) If there is no dance method, go to the Object prototype object prototype to find the dance method.

(4) If there is no more, an error will be reported.

一个小问题:在原型上添加方法需要注意的地方

有两种添加方法,第一种为上面的写法,直接通过 构造函数.prototype.方法名 进行添加;第二种为重定义构造函数的prototype,但是此种情况会丢失掉原有的constructor构造器,所以一定要再连接回去,例子如下:

function Star(name) {
	this.name = name;}Star.prototype = {
    dance:function(){
    	console.log("重定义prototype");
	}}Star.prototype.constructor = Star;
Copy after login

另外,类似于Array、String这些内置的类是不能这么处理的。

五、继承

这里就长话短说,首先我们要明确继承需要继承哪些东西,在前文中我们提到了定义构造函数的基本规则,即**公共属性定义到构造函数里面,公共方法我们放到原型对象身上。**我们所需要继承的东西也不外乎就这二者,公共属性的继承可以通过call()或者apply()进行this的指向定义,而公共方法可以通过原型对象的赋值进行处理,因此我们很容易想到如下的方法:

//定义一个父类function Father(name) {
	this.name = name;}Father.prototype.dance = function () {
	console.log('I am dancing');};//定义一个子类function Son(name, age) {
	Father.call(this, name);
	this.age = age;}//通过赋值的方法连接Son.prototype = Father.prototype;//为子类添加方法Son.prototype.sing = function () {
	console.log('I am singing');};
	let son = new Son('小红', 100);
	//此时父类也被影响了console.log(Father.prototype) 
	//{dance: ƒ, sing: ƒ, constructor: ƒ}
Copy after login

很显然,当我们只想修改子类里面的方法时,显然上述方法不太合适;因此 我们可以尝试new一个新的父类出来,代码如下:

function Father(name) {
	this.name = name;}Father.prototype.dance = function () {
	console.log('I am dancing');};function Son(name, age) {
	Father.call(this, name);
	this.age = age;}Son.prototype = new Father();Son.prototype.sing = function () {
	console.log('I am singing');};let son = new Son('小红', 100);console.log(Father.prototype) 
	//{dance: ƒ, constructor: ƒ}
Copy after login

六、class语法糖

对于以前了解过面向对象编程的程序员来讲,上述关于继承的写法属实让人有些难以接受,因此在es6里面新增了一个语法糖来更方便更便捷地书写继承,这里就直接上代码了;

class Father {
	constructor(name) {
		this.name = name;
	}
	dance() {
		console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在跳舞");
	}}class Son extends Father {
	constructor(name, age) {
		super(name);
		this.age = age;
	}
	sing() {
		console.log("我是" + this.name + ",我今年" + this.age + "岁," + "我在唱歌");
	}}let obj = new Son('小红', 19);
	obj.sing();obj.dance();
Copy after login

分析一下上面代码,首先一个类(构造函数)里面依旧为两部分,即公共属性和公共方法,constructor() 里面存放了该构造函数的公共属性,后面接着的便是公共方法,extends 关键字表示继承的是哪个类,super() 便是将里面父类里面相应的公共属性拿出来,这样看下来便可以将代码规整许多。

相关推荐:javascript学习教程

The above is the detailed content of A brief analysis of JavaScript inheritance and prototype chain. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:csdn.net
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