只有函数有prototype属性,所有对象都有__proto__属性;实例的__proto__严格指向其构造函数的prototype,构成原型链查找基础。

隐式原型 __proto__ 和显式原型 prototype 是 JavaScript 原型机制的两个核心概念,它们作用对象不同、存在时机不同、用途也不同,但又紧密关联。
谁有 prototype?只有函数才有
prototype 是函数(Function)对象独有的属性,一定义函数就自动存在,值默认是一个空对象({})。它不是给函数自己用的,而是为将来用 new 创建的实例准备的“共享模板”。
-
function Foo() {}→Foo.prototype自动存在,类型是对象 -
const arr = []→Array.prototype存在,所以arr.push能用 -
const fn = () => {}→ 箭头函数没有prototype属性(它不是构造函数) -
Function.prototype.bind()返回的函数也没有prototype
谁有 __proto__?所有对象都有
__proto__ 是每个对象(包括函数、数组、普通对象、甚至 Function.prototype)都有的内部属性,指向它的“原型对象”。它是对象查找属性时向上追溯的链路入口。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
-
const obj = {}→obj.__proto__ === Object.prototype -
const arr = []→arr.__proto__ === Array.prototype -
function Foo() {}→Foo.__proto__ === Function.prototype(因为函数本身是Function构造出来的) -
Object.prototype.__proto__是null,这是原型链终点
它们怎么对应?一句话:实例的 __proto__ 指向其构造函数的 prototype
这个关系只在通过 new 构造时自然建立:
-
function Car() {}→Car.prototype是一个对象 -
const c1 = new Car()→c1.__proto__ === Car.prototype(严格相等) - 因此,
c1能访问Car.prototype上的方法和属性
但要注意例外情况:
-
const o = Object.create({a: 1})→o.__proto__ === {a: 1},不经过构造函数,直接指定原型 -
const obj = {x: 1}→ 它没有构造函数意义上的prototype,但obj.__proto__仍指向Object.prototype
为什么不能混用?语义和规范层面都不同
prototype 是显式设计的共享接口,供开发者扩展;__proto__ 是运行时内部链接,用于属性查找。ECMAScript 规范中正式推荐用 Object.getPrototypeOf(obj) 代替 obj.__proto__,因为后者已被标记为废弃(尽管浏览器仍支持)。
- 写法上:
obj.__proto__ = xxx会破坏原型链,影响性能且不可靠 - 替代方案:
Object.setPrototypeOf(obj, xxx)或更安全的Object.create(xxx) - 读取建议:
Object.getPrototypeOf(obj)更标准、兼容性更好
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










