我所理解的原型与原型链

157 阅读2分钟

前言

浅聊 JavaScript 中的原型概念,理清 prototype 和__proto__ 的关系,图解原型链是怎样的一个结构。参考了几篇文章,简单聊聊我对原型的理解。知识水平有限,如果文章有什么错误之处,望指出。

JavaScript 中的原型

在 JavaScript 中, 原型(prototype)是联结每一个函数和对象的对象。默认情况下,每个函数都有原型对象。并且函数的原型(prototype)是可访问和可修改的。

在原型对象(prototype)上附加的属性,将会在其构造函数的所有实例中共享。

function Student(){
    this.name = "Zhangsan"
    this.gender = "male"
}
Student.prototype.age = 15
​
var studObj = new Student();
console.log(studObj.age); // 15

任何通过字面语法或者 new 关键字创建的对象都包含 __proto__属性,这个属性指向创建此对象的函数的原型对象(prototype)。

function Student(){
    this.name = "Zhangsan"
    this.gender = "male"
}
​
var studObj = new Student();
​
console.log(Student.prototype); // object
console.log(studObj.__proto__); // objectconsole.log(typeof Student.prototype); // object
console.log(typeof studObj.__proto__); // objectconsole.log(Student.prototype === studObj.__proto__); // true

对象的原型

建议使用 Object.getPrototypeOf(obj) 而不是 __proto__访问原型对象(prototype)。

function Student(){
    this.name = "Zhangsan"
    this.gender = "male"
}
​
var studObj = new Student();
var proto = Object.getPrototypeOf(studObj1);  // 返回 Student 的 Prototypeconsole.log(proto.constructor) // 返回 Student 函数

原型链

function Student(){
    this.name = "Zhangsan"
    this.gender = "male"
}
​
var studObj = new Student();
​
studObj.toString(); // '[object Object]'
Student.prototype.__proto__ === Object.prototype // true

上述例子中,Student 中并没有定义 toString() 方法,那么它是从哪里找到 toString() 的呢?

  1. JavaScript 引擎检查 toString() 方法是否存在于 studObj ?
  2. 如果找不到,那么就会往 studObj.__proto__ 所指向的 Student 的 prototype 对象上寻找。
  3. 如果还是找不到,通过 studObj.__proto__.__proto__ 这个原型对象的原型对象,它会到 Object.prototype 对象查找 toString() 方法。
  4. 最后,我们在 Object.prototype 对象上找到了 toString() 并执行它。
  5. 或者,如果达到了原型链顶端,还是找不到这个方法,则返回 undefined

JavaScript 实现这种查找功能所依赖的原型的链式结构,就称为原型链

image.png

小结

  1. 原型(prototype)是指函数上的一个对象。__proto__ 是一个函数实例化对象的一个属性,指向这个函数的原型。
  2. 通过对象上的 __proto__ 指向函数的原型对象(prototype),函数的原型的__proto__再指向 函数原型对象的原型,一层一层往上所构建的结构称为原型链。
  3. 原型和原型链的作用包括但不限于:
    1. 作为 函数实例化的对象的模板
    2. 通过原型链向上查找对象的属性和方法
    3. 通过原型链实现对象的继承

拓展

  1. new 做了什么
  2. 如何为 Object.prototype 新增属性
  3. class 是如何实现的,constructor 是什么

参考资料

  1. Prototype in JavaScript
  2. Inheritance in JavaScript
  3. 基于原型的编程 -- wiki