😀
在 JavaScript 中,prototype 和 __proto__ 构成了对象原型链的基础,理解这两个概念对于掌握 JavaScript 高级功能至关重要。本文主要记录这两个属性在实际应用中的作用和常见问题。

prototype

prototype 是每个函数对象特有的属性,用于定义那些由特定函数构造的所有实例共享的属性和方法。这意味着可以使用 prototype 属性为对象类添加功能:
在这个例子中,displayInfo 方法是在 Car.prototype 上定义的,这意味着 car1 和 car2 不需要各自存储这个函数的副本,它们通过原型链共享这个方法。

__proto__

__proto__ 是对象的内部属性,通常被称作隐式原型链(implicit prototype link),指向创建该对象的构造函数的 prototype。这也是我们常说的 JavaScript 的原型继承机制,这个机制使得对象可以访问原型链上的属性和方法。例如,使用前面定义的 Car 类:
这表明 car1 的 __proto__ 属性指向了 Car.prototype,从而可以通过原型链访问 displayInfo 方法。

常见问题和实际应用

  • 性能问题:
    • 在 JavaScript 中频繁使用 __proto__ 或直接操作原型(如 Object.prototype)可能会导致性能问题。
    • 每次访问对象的属性时,如果不在对象本身找到,解释器都必须沿着原型链查找,这可能会导致性能下降。
  • 原型污染:
    • 在多人协作的大型项目中,修改原型(尤其是全局对象如 Object 的原型)可能导致难以追踪的副作用,因为这会影响所有依赖这些原型的代码。
  • 使用 Object.create:
    • 创建具有特定原型的新对象时,可以使用 Object.create 方法。
    • 这也是创建继承链的一种更明确和更安全的方法。

关系和区别

  • 关系:
    • __proto__ 是对象用来实现继承的内部属性,指向创建这个对象的构造函数的 prototype。
    • 这也意味着通过同一个构造函数创建的所有对象都会共享同一个 prototype 对象,而 __proto__ 属性就是这种连接的具体实现。
  • 区别:
    • prototype 是函数的一个属性,定义了通过这个函数作为构造函数创建的对象的共同祖先。
    • __proto__ 则是每个对象的内部属性,指向其构造函数的 prototype。

原型链机制的作用过程

  • 当访问一个对象的属性时,如果对象本身没有这个属性,JavaScript 解释器就会通过对象的 __proto__ 属性去查找。这个过程会一直持续,直到属性被找到或者 __proto__ 链被追溯到 null(原型链的末尾)。这个机制是 JavaScript 原型继承的核心。
  • 例如,如果调用 person1.sayHello(),解释器首先查看 person1 是否有这个方法。如果没有,它会通过 person1.__proto__(即 Person.prototype)查找,这是因为 sayHello 方法定义在那里。

总结

理解 prototype 和 __proto__ 及其在 JavaScript 中的作用是任何高级开发者所必需的。通过正确使用这些属性,可以更有效地实现对象之间的继承和方法共享,同时避免一些常见的陷阱。
TypeScript——类型收缩与类型守卫JavaScript——typeof和instanceof