javascript中的原型链是什么?【教程】

7次阅读

原型链是javaScript对象查找属性时自动遵循的隐式路径:先查自身,再沿__proto__逐级向上直到NULL;__proto__指向构造函数prototype;hasOwnProperty等方法来自Object.prototype,推荐用Object.hasOwn()替代。

javascript中的原型链是什么?【教程】

原型链不是语法结构,而是 javascript 对象查找属性时自动遵循的一条隐式路径。理解它不靠背概念,而靠看属性访问时到底发生了什么。

对象读取属性时,引擎怎么找?

当你写 obj.name,JavaScript 引擎不会只查 obj 自身有没有 name 属性,而是按顺序检查:

  • 先查 obj 自身的属性(Object.hasOwn(obj, 'name') 可确认)
  • 如果没有,就去查 obj.__proto__(即 Object.getPrototypeOf(obj))上的 name
  • 如果还没找到,继续查 obj.__proto__.__proto__,直到为 null 为止

这条从实例 → 构造函数原型 → Object.prototypenull 的链条,就是原型链。它全程自动触发,你没调用任何方法,只是读了一个属性。

__proto__prototype 到底谁指向谁?

这是最容易绕晕的地方:两者名字像,但作用对象和时机完全不同。

立即学习Java免费学习笔记(深入)”;

  • function.prototype 是函数对象自带的属性,指向该函数作为构造器时,其实例将共用的那个原型对象
  • obj.__proto__ 是普通对象的内部属性(已不推荐直接访问),它的值等于创建 obj 的构造函数的 prototype
  • 比如 const arr = [],那么 arr.__proto__ === Array.prototype,而 Array.prototype.__proto__ === Object.prototype

别试图“改 __proto__ 来改变继承”,现代代码应统一用 Object.setPrototypeOf()class 语法,否则容易破坏 V8 的内联缓存优化。

为什么 hasOwnProperty 不在自己身上却能用?

因为 obj.hasOwnProperty('x') 是从原型链上借来的——obj.__proto__Object.prototype,而 hasOwnProperty 就定义在那上面。

  • 你可以用 obj.hasOwnProperty.call(someObj, 'x') 避免被子类重写覆盖
  • 但更安全的做法是用 Object.hasOwn(obj, 'x')(ES2022 新增),它不走原型链,直接查自身属性
  • 注意:for...in 会遍历整个原型链上的可枚举属性,而 Object.keys() 只返回自身的

原型链让方法复用成为可能,但也意味着修改 Object.prototype 会影响所有对象——这种操作在生产环境等同于埋雷。

class 写法时,原型链还在吗?

在。class 只是语法糖,底层仍是基于原型的机制。

  • class B extends A {} 会自动设置 B.prototype.__proto__ === A.prototype
  • new B()__proto__ 指向 B.prototype,再往上才是 A.prototype,最后是 Object.prototype
  • 箭头函数没有 prototype,不能当构造函数;普通函数即使没用 new,也有 prototype 属性(值为 {constructor: fn}

真正难调试的,往往不是链本身,而是某处意外覆盖了 constructor 或篡改了 __proto__,导致 instanceof 失效、或 new 实例后找不到预期方法。

text=ZqhQzanResources