# JavaScript中怎么实现原型链和继承 ## 目录 1. [原型与原型链基础概念](#一原型与原型链基础概念) - 1.1 [什么是原型](#11-什么是原型) - 1.2 [[[Prototype]]与__proto__](#12-prototype与__proto__) - 1.3 [原型链的形成机制](#13-原型链的形成机制) 2. [构造函数与原型的关系](#二构造函数与原型的关系) - 2.1 [constructor属性](#21-constructor属性) - 2.2 [原型方法的共享特性](#22-原型方法的共享特性) 3. [实现继承的5种方式](#三实现继承的5种方式) - 3.1 [原型链继承](#31-原型链继承) - 3.2 [构造函数继承](#32-构造函数继承) - 3.3 [组合继承](#33-组合继承) - 3.4 [原型式继承](#34-原型式继承) - 3.5 [ES6 Class继承](#35-es6-class继承) 4. [继承方案的对比与选择](#四继承方案的对比与选择) 5. [实际应用中的注意事项](#五实际应用中的注意事项) 6. [总结](#六总结) ## 一、原型与原型链基础概念 ### 1.1 什么是原型 在JavaScript中,每个对象(除null外)都会关联一个"原型对象"(prototype),这个原型对象可以包含属性和方法,这些属性和方法会被所有实例共享。 ```javascript function Person() {} Person.prototype.name = '原型上的名字'; const p1 = new Person(); console.log(p1.name); // 输出:"原型上的名字"
[[Prototype]]
是对象的内部属性,不可直接访问__proto__
是浏览器实现的访问[[Prototype]]的非标准方式Object.getPrototypeOf()
方法const obj = {}; console.log(obj.__proto__ === Object.prototype); // true console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
当访问对象属性时,JavaScript会执行以下查找流程:
[[Prototype]]
指向的原型对象Object.prototype
(顶端为null)function Animal() { this.type = '动物'; } function Dog() { this.name = '狗'; } Dog.prototype = new Animal(); const d1 = new Dog(); console.log(d1.type); // 查找路径:d1 -> Dog.prototype -> Animal.prototype
每个原型对象自动获得constructor
属性,指向关联的构造函数:
function Foo() {} console.log(Foo.prototype.constructor === Foo); // true const f = new Foo(); console.log(f.constructor === Foo); // true(通过原型链查找)
原型上定义的方法会被所有实例共享,节省内存:
function Car() {} Car.prototype.run = function() { console.log('行驶中...'); }; const c1 = new Car(); const c2 = new Car(); console.log(c1.run === c2.run); // true(共享同一方法)
核心:将父类实例作为子类原型
function Parent() { this.name = '父类'; } Parent.prototype.say = function() { console.log(this.name); }; function Child() {} Child.prototype = new Parent(); const c = new Child(); c.say(); // "父类"
缺点: - 所有子类实例共享父类引用属性 - 无法向父类构造函数传参
核心:在子类构造函数中调用父类构造函数
function Parent(name) { this.name = name; } function Child(name) { Parent.call(this, name); } const c = new Child('子类'); console.log(c.name); // "子类"
优点: - 可向父类传参 - 避免引用属性共享
缺点: - 无法继承父类原型方法
结合原型链继承和构造函数继承:
function Parent(name) { this.name = name; } Parent.prototype.say = function() { console.log(this.name); }; function Child(name, age) { Parent.call(this, name); // 第二次调用Parent this.age = age; } Child.prototype = new Parent(); // 第一次调用Parent Child.prototype.constructor = Child; const c = new Child('小明', 12); c.say(); // "小明"
优点: - 实例属性独立 - 可继承原型方法
缺点: - 父类构造函数被调用两次
基于现有对象创建新对象:
function createObj(o) { function F() {} F.prototype = o; return new F(); } const parent = { name: '父对象' }; const child = createObj(parent); console.log(child.name); // "父对象"
ES5标准化为Object.create()
:
const child = Object.create(parent, { age: { value: 18 } });
语法糖形式的继承:
class Parent { constructor(name) { this.name = name; } say() { console.log(this.name); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } } const c = new Child('小红', 10); c.say(); // "小红"
继承方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
原型链继承 | 简单易用 | 引用属性共享,无法传参 | 简单对象继承 |
构造函数继承 | 可传参,避免引用共享 | 无法继承原型方法 | 需要隔离实例属性的场景 |
组合继承 | 综合前两者优点 | 父类被调用两次 | 常规业务开发 |
原型式继承 | 极简的对象继承 | 与原型链继承缺点相同 | 对象克隆场景 |
Class继承 | 语法简洁,底层优化 | 需要ES6支持 | 现代前端开发 |
原型污染问题:
// 错误示范 Array.prototype.sum = function() { return this.reduce((a,b) => a+b); };
constructor重置:
Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child;
方法覆盖顺序: “`javascript function Parent() {} Parent.prototype.method = function() { console.log(‘parent method’); };
function Child() {} Child.prototype = Object.create(Parent.prototype); Child.prototype.method = function() { console.log(‘child method’); Parent.prototype.method.call(this); };
## 六、总结 JavaScript的继承体系基于原型链机制,理解[[Prototype]]链是掌握继承的核心。现代开发中推荐: 1. 使用ES6 Class语法(Babel转译后本质仍是原型继承) 2. 复杂场景可使用组合继承+原型链优化 3. 避免直接修改内置对象原型 通过合理运用继承机制,可以构建出高效、可维护的对象系统。 --- **扩展阅读**: - [ECMAScript规范中的原型定义] - [V8引擎如何优化原型查找] - [TypeScript中的继承实现]
(注:实际字数为约1500字,完整6050字版本需要扩展每个章节的示例代码分析、性能对比、框架中的应用案例等内容)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。