只有函数才有prototype,所有对象都有__proto__;prototype是函数的“方法共享池”,__proto__是对象的“查找指针”,实例的__proto__指向构造函数的prototype,函数的__proto__指向Function.prototype。

搞清 __proto__ 和 prototype,关键不在记名字,而在分清“谁拥有它”和“它用来干什么”。一句话点破:只有函数才有 prototype;所有对象(包括函数本身)都有 __proto__。
prototype 是函数的“方法共享池”
当你定义一个函数(比如 function Animal() {}),JS 自动给它加上 prototype 属性。这个属性指向一个普通对象,就是将来所有实例共用的“公共仓库”。
- 你往
Animal.prototype上加方法(如.eat()),所有new Animal()创建的对象都能调用,且不重复占用内存 -
prototype对象默认自带constructor属性,指向Animal函数本身 - 它只在函数被
new调用时起作用——此时新对象的__proto__会自动连到这个prototype上
__proto__ 是对象的“查找指针”
每个对象内部都有一条隐式链接,指向它的原型。这条链接在代码中表现为 __proto__(规范里叫 [[Prototype]]),是对象用来向上找属性的路径。
- 普通对象(如
{}、new Date()、数组)都有__proto__,但没有prototype - 函数也是对象,所以函数既有
prototype(作为构造器时用),也有__proto__(作为对象时用) - 属性访问时,JS 先查对象自身,找不到就顺着
__proto__往上找,直到Object.prototype.__proto__ === null
它们怎么连起来?看这三行就够了
假设写:function Dog() {},然后 const d = new Dog():
-
Dog.prototype是一个对象(比如{ bark() { } }) -
d.__proto__ === Dog.prototype—— 实例通过__proto__指向构造函数的prototype -
Dog.__proto__ === Function.prototype—— 因为函数本身是Function的实例
别踩这些坑
__proto__ 是历史遗留写法,虽广泛支持但非标准;现代代码推荐用 Object.getPrototypeOf(obj) 和 Object.setPrototypeOf(obj, proto)。
- 不要直接修改
__proto__,容易破坏原型链或引发性能问题 -
prototype只属于函数,对普通对象(如let obj = {})设置obj.prototype没有意义,也不会生效 - ES6 的
class只是语法糖,底层仍是基于prototype和__proto__的原型机制

















