JavaScript原型是函数的prototype属性,用于实例共享属性方法;原型链是通过__proto__向上查找的机制,终点为null。

JavaScript 原型是每个函数对象自带的 prototype 属性,它是一个普通对象,用来存放将来被该函数作为构造器创建的实例所共享的属性和方法。原型链则是对象在访问属性或方法时,沿着 __proto__ 链向上逐级查找的机制。
每个函数都有 prototype,但只有「被当构造器调用」的对象才继承它
你定义一个函数:
function Person(name) { this.name = name; }它立刻拥有 Person.prototype,这个对象默认带一个 constructor 属性指向 Person。但此时 Person.prototype 和 Person 本身毫无关系——直到你用 new Person()。
这时发生三件事:
- 创建一个新对象
- 将该对象的
__proto__指向Person.prototype - 执行
Person函数体,this绑定到这个新对象
所以不是“函数有原型所以能继承”,而是“new 操作符把实例的 __proto__ 指向了函数的 prototype”。
立即学习“Java免费学习笔记(深入)”;
__proto__ 不是标准写法,但浏览器普遍支持;Object.getPrototypeOf() 才是正解
__proto__ 是历史遗留属性,ECMAScript 规范并未强制要求其实现(尽管所有主流引擎都支持)。直接读写它容易引发混淆,尤其在类继承或 Proxy 场景下行为不一致。
正确方式是:
- 查原型:
Object.getPrototypeOf(obj) - 设原型(仅限可写对象):
Object.setPrototypeOf(obj, proto) - 创建带指定原型的新对象:
Object.create(proto)
比如:
const parent = { say() { return 'hi'; } };
const child = Object.create(parent);
console.log(Object.getPrototypeOf(child) === parent); // true
原型链终点是 Object.prototype,再往上是 null
所有普通对象最终都继承自 Object.prototype,而它的 __proto__ 是 null。这就是查找终止条件。
你可以验证:
console.log(Object.getPrototypeOf({}) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true
注意几个常见陷阱:
-
Array.prototype和Function.prototype都是Object.prototype的直接子对象,不是平级关系 -
typeof null返回"object",但它没有原型(Object.getPrototypeOf(null)报错) - 箭头函数没有
prototype属性,不能用new调用
真正容易被忽略的是:原型链只在「读取属性」时触发,赋值操作永远作用于对象自身。哪怕 obj.x = 1 的 x 原本在原型上,这次赋值也会在 obj 上新建一个同名自有属性——原型上的那个不会被修改,也不会被屏蔽以外的方式绕过。











