原型和原型链

118 阅读2分钟

JavaScript 中的原型和原型链对于我来说实在是太难了,为了这一篇文章,我大概准备了一个月,理解起来属实有些难度,不仅要懂 __proto__ 和 prototype 之间的关系,还要知道如何通过原型链实现继续,实现 new 的关键字。能力有限,这篇先理解一下原型原型链,一步一步实现 new 和 继承 

jsobj_full.jpg 先上一张图,原型的指向都在这张图里面,我会一点一点的拆解出来

prototype

每个函数都会创建一个prototype属性,这个属性是一个对象,包含应该由特定引用类型的实例 共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处 是,在它上面定义的属性和方法可以被对象实例共享。原来在构造函数中直接赋给对象实例的值,可以 直接赋值给它们的原型。这个属性会指向函数的原型对象:

const Foo = function(name) {
	this.name = name
}
Foo.prototype.age = 18;
const f1 = new Foo("Lius");
console.log(f1.name) // Lius
console.log(f1.age) // 18

理解一下:

  • 构造函数 Foo 
  • 实例对象 Foo 
  • 在构造函数里面定义了 name 属性
  • 在 Foo 的 prototype 属性上面定义了 age 属性 并赋值为 18

上述例子中函数的 prototype 指向了一个对象,而这个对象正是调用构造函数时创建的实例的原型,也就是通过new 关键字创建出来的 f1 实例对象;

拆分上图: image.png

constructor

无论何时,只要创建一个函数,就会按照特定的规则为这个函数创建一个prototype 属性(指向 原型对象)。默认情况下,所有原型对象自动获得一个名为constructor 的属性,指回与之关联的构 造函数。即 Foo.prototype.constructor === Foo 

拆分上图: image.png

__ proto __

这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。即: f1.__proto__===Foo.prototype  注意他们的区别 __proto__ 存在于实例对象上面, prototype 存在于构造函数

拆分上图: image.png 到此为止, JS中的原型和原型链可以算是说完了,但是可以继续深究下去,根据最开始的图可以看到 var Foo = function()  Foo 也是有原型的。

Foo() 的原型

定义的函数的原型是 Function , 也就是说 Foo()Function 的实例对象,那么函数定义可以写成 var Foo = new Function() 。其实并没有必要去深究这么多,我们只需要知道在JS中原型的指向就可以了,根据上图还可以看出 Function 是 Object 的原型实例,同样 Object 也是 Function 的原型实例。形成了一个闭环,这不是我们关注的重点,重点是要根据JS的原型来解释 new 关键字和如何通过原型来实现继承。

请关注下篇 new 和 继承