应将通用行为定义在原型上、个体数据放在实例中:方法统一挂prototype以节省内存并确保共享,实例属性在构造函数中初始化;避免在原型上放置可变对象以防意外共享。

核心就一条:把通用行为放原型上,把个体数据放实例里。这样既省内存,又保证每个实例操作自己的数据。
方法统一挂 prototype,避免重复创建
构造函数内部定义方法,每次 new 都会生成一份新函数;而挂到 prototype 上,所有实例共用同一份代码。
- ✅ 正确写法:在 Person.prototype.sayHello = function() { ... } 中定义行为
- ❌ 错误写法:在 function Person() { this.sayHello = function() { ... } } 中定义
- 好处:100 个实例只有一份 sayHello 函数,console.log(p1.sayHello === p2.sayHello) 返回 true
区分共享与独有:属性不乱放
原型对象适合放不可变值(如字符串、数字)或纯函数,但绝不能直接放可变对象(如数组、空对象)作为原型属性,否则所有实例会意外共享同一份引用。
- ✅ 实例专属数据(this.name、this.head、this.root)必须在构造函数中初始化
- ✅ 共享逻辑(append()、inorder()、toArray())一律定义在 prototype 上
- ⚠️ 反例:Person.prototype.cache = {} → 多个实例调用会互相覆盖
自定义结构(链表/树)推荐原型用法
链表的 insert、树的 search 这类算法逻辑不依赖私有闭包,天然适合原型共享。
- 构造函数只负责初始化结构状态:this.head = null、this.size = 0
- 所有遍历、增删、计算类方法都写在 LinkedList.prototype 或 BinaryTree.prototype 上
- 调用时 this 自动指向当前实例,无需手动绑定,逻辑清晰且隔离性强
注意 this 绑定是动态的,不是“共享 this”
原型方法被多个实例共用,但每次调用时 this 都自动指向发起调用的那个实例,不是共享同一个 this,而是共享同一段函数体。
- p1.sayHello() 中的 this === p1
- p2.sayHello() 中的 this === p2
- 只要不是箭头函数,且用 obj.method() 形式调用,this 就精准归属当前对象
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











