静态属性属于构造函数自身,原型属性属于其prototype;前者通过构造函数访问、不继承,后者通过实例或prototype访问、自动继承;静态方法this指向构造函数,原型方法this指向实例。

静态属性和原型属性在 JavaScript 中看似都能被“复用”,但它们服务的对象、访问路径、继承行为和修改影响完全不同。搞清区别,才能避免误改共享状态或错失继承能力。
归属对象不同:构造函数本身 vs 构造函数的 prototype
静态属性直接挂在函数(构造函数)上,比如 Person.count = 0;它属于 Person 这个函数对象自己。原型属性则必须通过 Person.prototype.sayHello = function(){} 定义,它属于 Person.prototype 这个对象,是所有实例共享的“行为蓝图”。
- 访问静态属性只能用 Person.count,实例 person.count 是 undefined
- 访问原型属性既可用 person.sayHello(),也可用 Person.prototype.sayHello()
- 构造函数无法直接读取自己的 prototype 上的属性(Person.sayHello 是 undefined)
共享逻辑不同:类级单例 vs 实例间共用通道
静态属性是真正的“一份全局值”,所有地方读写都指向同一个内存位置,适合做类计数器、配置开关、工具常量等跨实例协调用途,例如 API.timeoutMs = 5000。
原型属性虽也“共享”,但它本质是为每个实例提供统一的行为入口或默认数据,不是为了存储状态。比如 Array.prototype.last 是所有数组都能调用的方法,但你不能靠它存某个数组的“最后操作时间”——那该用实例属性。
- 改 Person.totalCreated++,所有后续调用都看到新值
- 改 Person.prototype.greet = () => 'Hi',所有已有和新建的 person 实例立刻获得新行为
- 但给 person.greet = () => 'Hey' 赋值后,只覆盖该实例自己的 greet,不影响原型或他人
this 指向与使用意图不同:不依赖实例 vs 天然绑定实例
静态方法内部的 this 指向构造函数自身(如 Person),它不关心有没有实例,也不需要访问 this.name 这类实例数据;而原型方法的 this 总是指向调用它的那个实例,天然支持访问 this.status、this.id 等实例属性。
- 静态方法适合:创建工厂(User.createAdmin())、校验工具(Date.isValid())、类级配置(Logger.setLevel('debug'))
- 原型方法适合:实例行为(user.isActive())、计算属性(array.sum())、链式调用(query.where().limit().exec())
继承表现不同:不自动传递 vs 自动进入原型链
子类(如 Student)不会自动拥有父类(Person)的静态属性,Student.count 是 undefined,除非手动设置 Student.count = Person.count 或用 Object.setPrototypeOf(Student, Person) 建立构造函数间的继承。
但原型属性天然存在于原型链中:new Student() 可直接调用 Person.prototype.sayHello(),也能在 Student.prototype 上重写它,实现多态。
- 静态属性需显式继承或复制,否则断开
- 原型属性随 new 操作自动链接,子类实例可无缝使用、覆盖、扩展
- 这也是为什么 ES6 class 的 static method 不会被 extends 继承,而 method() 会
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











