JavaScript基于原型的面向对象编程详解
JavaScript采用基于原型(Prototype)的对象系统而非传统的类(Class)。理解实例与原型之间的链接关系,是掌握其面向对象编程的关键。
结果或目标
在JavaScript中构建可重用的对象模板,实现属性封装与方法共享,并理解实例如何通过原型链访问定义在构造函数上的行为。
准备条件
- 熟悉JavaScript基本语法,包括函数、对象字面量和变量作用域。
- 了解原型链的基本概念:对象在访问属性时,若自身未找到,将沿原型链向上查找。
真实操作顺序
第1步:定义构造函数并声明实例属性
使用函数作为构造函数,通过 this 关键字为每个新创建的实例分配独立的属性。这些属性属于实例自身(Own Properties),通常是 Public 属性,可直接被外部读取或修改。
function A() {
this.className = "ClassA"; // 添加Public属性
}
目的:初始化实例状态。
重要参数:确保属性名前缀包含 this,否则无法绑定到当前实例上下文。
第2步:扩展原型方法
为了节省内存并实现方法共享,不应在构造函数内部定义方法,而应将这些方法添加到构造函数的 prototype 对象上。这样所有由该构造函数创建的实例都能共享同一个方法引用。
// 添加一方法
A.prototype.getClassName = function() {
return this.className; // this指代A实例,而不是prototype
};
目的:实现行为的复用与继承的基础。
入口:指向构造函数的 prototype 属性。
第3步:创建实例并验证原型链关系
使用 new 关键字调用构造函数创建对象。此时,实例的内部原型([[Prototype]],在部分浏览器或环境中可通过 __proto__ 访问)会指向构造函数的 prototype 对象。
// 声明一对象
var AObj = new A();
// 验证原型关系 (注意: __proto__ 是非标准但广泛支持的访问方式)
console.log(AObj.__proto__ === A.prototype); // 现代浏览器下为 true
完成状态:能够访问到 A.prototype.getClassName 方法,且返回值正确。
第4步:理解属性保护机制(Private vs Public)
由于直接定义的属性默认是 Public 的,若需隐藏内部状态,可利用闭包原理。但在传统的基于原型的模式中,严格意义上的 Private 属性通常需要借助函数作用域来模拟,或者简单地通过约定不使用 this 来声明局部变量(但这会导致该方法无法访问该变量,除非使用闭包)。原文提到的简易做法是通过不暴露属性名或使用命名规范来约定保护,例如:
// 尝试保护 className,但不推荐此写法,因为外部仍可遍历枚举
this._className = "ClassA";如需真正的私有变量,建议使用 ES6 Class 语法或更复杂的闭包模式,但在原生 Prototype 模式下,通常依靠 _ 前缀等社区约定来实现“伪私有”。
第5步:探索动态原型扩展
JavaScript 允许通过实例的 __proto__ 直接修改原型的属性,这会立即影响该类型的所有现有及未来实例。虽然这在技术上可行,但**不推荐在生产环境中这样做**,因为它破坏了封装性并可能导致意外的全局行为改变。
// 不推荐的动态扩展
s.__proto__.hjK = function() {
return "hjK";
};
alert(s.hjK()); // 可以访问
完成判断
- 实例能够通过自身作用域访问 Public 属性。
- 实例能够通过原型链访问定义在
prototype上的方法。 - 理解
AObj.__proto__ === A.prototype这一核心等式的含义。
简要总结
JavaScript 的原型链机制是其面向对象的核心。通过在构造函数中定义实例属性,在 prototype 上定义共享方法,可以实现灵活的对象建模。需注意 __proto__ 的直接操作虽能扩展功能,但应保持谨慎。以上就是 JavaScript 基于原型的面向对象编程的详细内容,更多关于 JavaScript 基础教程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













