跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
JavaScript继承方式
”︁
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= JavaScript继承方式 = '''JavaScript继承方式'''是面向对象编程(OOP)中的核心概念之一,它允许一个对象(子类)基于另一个对象(父类)的属性和方法来构建,从而实现代码复用和层次化设计。JavaScript提供了多种继承方式,每种方式都有其特点和适用场景。本文将详细介绍这些继承方式,帮助初学者和高级开发者理解并选择合适的方法。 == 1. 原型链继承 == 原型链继承是JavaScript中最基本的继承方式,它通过将子类的原型对象指向父类的实例来实现继承。 === 基本实现 === <syntaxhighlight lang="javascript"> // 父类 function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise.'); }; // 子类 function Dog(name) { this.name = name; } // 继承 Dog.prototype = new Animal(); var dog = new Dog('Rex'); dog.speak(); // 输出: "Rex makes a noise." </syntaxhighlight> === 特点 === * 子类实例共享父类的属性和方法。 * 简单易用,适合简单的继承需求。 * 缺点是所有子类实例共享同一个父类实例的属性,可能导致数据污染。 == 2. 构造函数继承 == 构造函数继承通过在子类构造函数中调用父类构造函数来实现继承,使用`call`或`apply`方法。 === 基本实现 === <syntaxhighlight lang="javascript"> function Animal(name) { this.name = name; this.speak = function() { console.log(this.name + ' makes a noise.'); }; } function Dog(name) { Animal.call(this, name); // 调用父类构造函数 } var dog = new Dog('Rex'); dog.speak(); // 输出: "Rex makes a noise." </syntaxhighlight> === 特点 === * 子类实例拥有独立的父类属性副本,不会共享数据。 * 无法继承父类原型上的方法,只能继承父类构造函数中定义的属性和方法。 == 3. 组合继承 == 组合继承结合了原型链继承和构造函数继承的优点,是最常用的继承方式之一。 === 基本实现 === <syntaxhighlight lang="javascript"> function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise.'); }; function Dog(name) { Animal.call(this, name); // 构造函数继承 } Dog.prototype = new Animal(); // 原型链继承 Dog.prototype.constructor = Dog; // 修复构造函数指向 var dog = new Dog('Rex'); dog.speak(); // 输出: "Rex makes a noise." </syntaxhighlight> === 特点 === * 子类实例既拥有独立的属性副本,又能继承父类原型上的方法。 * 缺点是调用了两次父类构造函数(一次在`call`,一次在`new Animal()`),可能造成性能问题。 == 4. 原型式继承 == 原型式继承基于一个已有对象创建新对象,无需显式定义构造函数。 === 基本实现 === <syntaxhighlight lang="javascript"> var animal = { name: 'Animal', speak: function() { console.log(this.name + ' makes a noise.'); } }; var dog = Object.create(animal); dog.name = 'Rex'; dog.speak(); // 输出: "Rex makes a noise." </syntaxhighlight> === 特点 === * 简单灵活,适合不需要构造函数的场景。 * 类似于原型链继承,所有实例共享原型对象的属性。 == 5. 寄生式继承 == 寄生式继承是对原型式继承的增强,通过在创建新对象时添加额外方法来实现。 === 基本实现 === <syntaxhighlight lang="javascript"> function createDog(name) { var dog = Object.create(animal); dog.name = name; dog.bark = function() { console.log(this.name + ' barks.'); }; return dog; } var dog = createDog('Rex'); dog.speak(); // 输出: "Rex makes a noise." dog.bark(); // 输出: "Rex barks." </syntaxhighlight> === 特点 === * 可以为新对象添加独有的方法。 * 缺点是方法无法复用,每个实例都会创建新的方法副本。 == 6. 寄生组合式继承 == 寄生组合式继承是组合继承的优化版本,避免了调用两次父类构造函数的问题。 === 基本实现 === <syntaxhighlight lang="javascript"> function inheritPrototype(child, parent) { var prototype = Object.create(parent.prototype); prototype.constructor = child; child.prototype = prototype; } function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(this.name + ' makes a noise.'); }; function Dog(name) { Animal.call(this, name); } inheritPrototype(Dog, Animal); var dog = new Dog('Rex'); dog.speak(); // 输出: "Rex makes a noise." </syntaxhighlight> === 特点 === * 只调用一次父类构造函数,效率更高。 * 是ES6之前最理想的继承方式。 == 7. ES6 Class继承 == ES6引入了`class`和`extends`关键字,使继承更加简洁和直观。 === 基本实现 === <syntaxhighlight lang="javascript"> class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } class Dog extends Animal { constructor(name) { super(name); } bark() { console.log(this.name + ' barks.'); } } const dog = new Dog('Rex'); dog.speak(); // 输出: "Rex makes a noise." dog.bark(); // 输出: "Rex barks." </syntaxhighlight> === 特点 === * 语法简洁,易于理解。 * 底层仍然基于原型链实现,是语法糖。 == 继承方式对比 == 以下是各种继承方式的对比表: {| class="wikitable" |- ! 继承方式 !! 优点 !! 缺点 |- | 原型链继承 || 简单易用 || 共享属性,可能污染数据 |- | 构造函数继承 || 独立属性副本 || 无法继承原型方法 |- | 组合继承 || 独立属性副本 + 继承原型方法 || 调用两次父类构造函数 |- | 原型式继承 || 灵活,无需构造函数 || 共享属性 |- | 寄生式继承 || 可为实例添加独有方法 || 方法无法复用 |- | 寄生组合式继承 || 高效,只调用一次父类构造函数 || 实现稍复杂 |- | ES6 Class继承 || 语法简洁,易于维护 || 需支持ES6环境 |} == 实际应用案例 == === 场景:UI组件库 === 在开发UI组件库时,通常需要一个基础组件(如`BaseComponent`),其他组件(如`Button`、`Input`)继承自它。使用ES6 Class继承可以清晰地表达这种关系: <syntaxhighlight lang="javascript"> class BaseComponent { constructor(element) { this.element = element; } render() { console.log('Rendering base component'); } } class Button extends BaseComponent { constructor(element, label) { super(element); this.label = label; } render() { super.render(); console.log('Rendering button with label: ' + this.label); } } const button = new Button('#button', 'Submit'); button.render(); // 输出: // "Rendering base component" // "Rendering button with label: Submit" </syntaxhighlight> === 场景:游戏开发 === 在游戏中,角色通常有共同的属性和方法(如`Character`),而具体角色(如`Player`、`Enemy`)继承自它: <syntaxhighlight lang="javascript"> class Character { constructor(name, health) { this.name = name; this.health = health; } attack() { console.log(this.name + ' attacks!'); } } class Player extends Character { constructor(name, health, level) { super(name, health); this.level = level; } levelUp() { this.level++; console.log(this.name + ' leveled up to ' + this.level); } } const player = new Player('Hero', 100, 1); player.attack(); // 输出: "Hero attacks!" player.levelUp(); // 输出: "Hero leveled up to 2" </syntaxhighlight> == 总结 == JavaScript提供了多种继承方式,每种方式都有其适用场景: * 对于简单需求,可以使用原型链继承或原型式继承。 * 需要独立属性副本时,使用构造函数继承或组合继承。 * 追求高效时,选择寄生组合式继承。 * 在现代开发中,优先使用ES6 Class继承。 理解这些继承方式的原理和差异,有助于在项目中做出合理的选择。 [[Category:编程语言]] [[Category:JavaScript]] [[Category:Javascript面向对象编程]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)