原型对象在打印时容易让人头晕的地方

453 阅读2分钟

什么是JavaScript类

JavaScript类其实是原型继承的语法糖

首先我们创建一个类:

  class Grandfather {
	constructor() {
	  this.state = 1;
	}
	say() {
	  console.log("爷爷");
	}
	grandfather() {}
  }

其实我们知道,这么写等价于:

  function Grandfather() {
	this.state = 1;
  }
  Grandfather.prototype.say = function () {
	console.log("爷爷");
  };
  Grandfather.prototype.grandfather = function () {};

new Grandfather()打印出来是这个样子:

Pasted image 20220810183619.png

我们new出来的实例对象里都会有一个原型对象__proto__(在浏览器里会显示为[[Prototype]],这玩意其实在最里层写着呢)

你可以依次点击Father的[[Prototype]]-> Object的[[Prototype]]找到__proto__属性, 你会发现第一层是Father的[[Prototype]],第二层是Object的[[Prototype]]

原型对象里有类里的method 并且原型对象里都会有一个构造函数构造函数里的原型对象又指向刚才那个原型对象

套娃 原型对象里有构造函数 构造函数里又有原型对象

Pasted image 20220810183905.png

所以,类中的this实际上是new出来的实例对象 而类中的方法全部被添加到实例对象原型对象中了 理解了这点接下来就不难理解了

如何去称呼一个原型对象

接下来我们再创建两个类,打印出来看一看

  class Father extends Grandfather {
	constructor() {
	  super();
	}
	say() {
	  console.log("爸爸");
	}
	father() {}
  }

  const baba = new Father();
  console.log("baba", baba);

  class Boy extends Father {
	constructor() {
	  super();
	}
	say() {
	  console.log("my name");
	}
	boy() {}
  }
  const boy = new Boy();
  console.log("boy", boy);

打印出来你会发现一个好玩的规律:

Pasted image 20220810190456.png

注意箭头和下面红框的关系 虽然[[Prototype]]的名字是Grandfather但里面的属性实则是father类中定义的

因为大家(类和构造函数)都是在操作自己的原型对象,给自己的原型对象增加了各种各样的属性,但这个原型对象的名字却是自己上级的名字...总有种研究生再给导师写论文的感觉

所以我建议一般在称呼一个原型对象时,不要使用此原型对象的名字(即[[Prototype]]后写的名字),而是使用它constructor名+实例+的原型对象来描述,比较不容易混淆一点....

比如第一个框我们可以叫做Father实例的原型对象