怎样理解javascript的原型链【教程】

7次阅读

javaScript原型链是属性查找的真实路径,由[[prototype]]隐式链接构成,从对象自身向上遍历至NULL;__proto__指向构造函数的prototype,后者仅函数拥有,Object.getPrototypeOf()是标准获取方式;class只是语法糖,原型链依然存在且只影响读取。

怎样理解javascript的原型链【教程】

javascript 的原型链不是“继承机制的模拟”,而是对象查找属性时真实发生的路径。它不靠 class 关键字驱动,而由每个对象内部的 [[Prototype]] 隐式链接构成——这个链接指向另一个对象,查找失败时就顺着它继续找,直到为 null 为止。

为什么 obj.toString() 能用,但 obj 上并没有定义它?

因为 toStringObject.prototype 上。当你访问一个对象上不存在的属性时,js 引擎会自动沿着 [[Prototype]] 链向上查找:

  • 先查 obj 自身是否有 toString
  • 没有 → 查 obj.__proto__(即 Object.getPrototypeOf(obj)
  • 还没找到 → 继续查它的 __proto__,也就是 Object.prototype
  • 找到了 → 返回该方法
  • 如果一直查到 null 还没找到,就返回 undefined

__proto__prototypeObject.getPrototypeOf() 到底谁对应谁?

三者常被混用,但职责完全不同:

  • __proto__ 是每个实例对象上的访问器属性(已废弃但广泛支持),指向其构造函数的 prototype
  • prototype 是每个函数对象才有的属性,仅在该函数被用作构造函数时生效,它的值是将来所有实例的 [[Prototype]]
  • Object.getPrototypeOf(obj) 是标准、安全的获取对象原型的方式,应替代 obj.__proto__

例如:function Foo() {},那么 new Foo().__proto__ === Foo.prototype,且 Object.getPrototypeOf(new Foo()) === Foo.prototype

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

class 写代码,原型链还存在吗?

存在,而且没变。es6class 只是语法糖,底层仍基于原型链工作:

  • class B extends A 实际设置的是 B.prototype.__proto__ = A.prototype
  • super() 调用的是父类构造函数,不改变原型关系
  • 静态方法挂在 B 函数本身上,而非 B.prototype;它们不会出现在实例的原型链中

可以验证:class C {},然后 Object.getPrototypeOf(new C()) === C.prototype,结果为 true

真正容易被忽略的是:原型链只影响读取(get),不影响赋值(set)。给实例属性赋值时,永远写在实例自身,不会触发原型上的同名属性更新——这也是为什么修改 Array.prototype.push 不会影响已有数组的 push 行为,除非你显式覆盖或重定义它。

text=ZqhQzanResources