面向对象
来源:互联网 发布:赚钱红包软件秒到账 编辑:程序博客网 时间:2024/06/12 20:30
- 1. 前言
- 2. 约束
- 3. 实现方式
- 3.1. 基于 ES5 的继承实现
- 3.1.1. 构造函数
- 3.1.2. 继承实现
- 3.1.2.1. 原型链继承
- 3.1.2.2. 构造继承
- 3.1.2.3. 实例继承
- 3.1.2.4. 拷贝继承
- 3.1.2.5. 组合继承
- 3.1.2.6. 寄生组合继承
- 3.2. 基于 ES6 的继承实现
- 3.2.1. 构造函数
- 3.2.2. 继承实现
1. 前言
面向对象语言不得不提到继承的概念,JavaScript作为脚本语言对于面向对象的实现并不严谨,但足够解决问题,此文就继承的实现进行探讨。
2. 约束
- 确定JavaScript语言使用的标准。
- 创建一个父类的构造函数。
- 继承的实现。
3. 实现方式
3.1. 基于 ES5 的继承实现
3.1.1. 构造函数
// 定义一个乐器的构造函数function Instrument (name) { // 构造属性 this.name = name || 'Instrument'; // 构造方法 this.introduce = function () { console.log('I am', this.name, '.'); };};Instrument.prototype.play = function (note) { console.log(this.name, 'play', note);};
3.1.2. 继承实现
3.1.2.1. 原型链继承
核心:将父类的实例作为子类的原型
function Guitar () {};Guitar.prototype = new Instrument();Guitar.prototype.name = 'Guitar';
优点:
- 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
- 父类新增原型方法/原型属性,子类都能访问到
- 简单,易于实现
缺点:
- 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
- 无法实现多继承
- 来自原型对象的引用属性是所有实例共享的
- 创建子类实例时,无法向父类构造函数传参
3.1.2.2. 构造继承
核心:将父类的实例作为子类的原型
function Guitar (name) { Instrument.call(this); this.name = name || 'Guitar';};
优点:
- 解决了原型链继承中,子类实例共享父类引用属性的问题
- 创建子类实例时,可以向父类传递参数
- 可以实现多继承(call多个父类对象)
缺点:
- 实例并不是父类的实例,只是子类的实例
- 只能继承父类的实例属性和方法,不能继承原型属性/方法
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3.1.2.3. 实例继承
核心:构造时为父类实例添加新特性,作为子类实例返回
function Guitar (name) { var instance = new Instrument(); this.name = name || 'Guitar'; return instance;};
优点:
- 不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
- 实例是父类的实例,不是子类的实例
- 不支持多继承
3.1.2.4. 拷贝继承
核心:构造时,拷贝父类实例的 prototype 属性
function Guitar (name) { var instance = new Instrument(); for (var p in instance) { Guitar.prototype[p] = instance[p]; }; Guitar.name = name || 'Guitar';};
优点:
- 支持多继承
缺点:
- 效率较低,内存占用高(因为要拷贝父类的属性)
- 无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
3.1.2.5. 组合继承
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Guitar (name) { Instrument.call(this); this.name = name || 'Guitar'; };Guitar.prototype = new Instrument();
优点:
- 弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
- 既是子类的实例,也是父类的实例
- 不存在引用属性共享问题
- 可传参
- 函数可复用
缺点:
- 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
3.1.2.6. 寄生组合继承
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Guitar (name) { Instrument.call(this); this.name = name || 'Guitar'; };(function () { // 创建一个没有实力方法的类 var Super = function () {}; Super.prototype = Animal.prototype; // 将实例作为子类的原型 Guitar.prototype = new Super();})();
优点:
- 堪称完美
缺点:
- 实现较为复杂
3.2. 基于 ES6 的继承实现
3.2.1. 构造函数
// 定义一个乐器的构造函数class Instrument { constructor (name) { // 构造属性 this.name = name || 'Instrument'; // 构造方法 this.introduce = () => { console.log('I am', this.name, '.'); }; } play (note) { console.log(this.name, 'play', note); }}
3.2.2. 继承实现
核心:ES6 实现了继承的 API 接口
class Guitar extends Instrument { constructor (name) { // 执行构造函数的方法 super(name); }}
优点:
- 接口优雅,API 规范
缺点:
- 需要 ES6 编译环境
- 无法实现多继承
阅读全文
1 0
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- 面向对象
- ubuntu下最全的软件安装、卸载、查看命令
- 1040. 有几个PAT(25) PAT乙级真题
- docker命令小结
- 深入浅出MyBatis-Sqlsession
- Eclipse怎么设置自动删除空白行和语句后多余空格?
- 面向对象
- 406. 和大于S的最小子数组
- 大咖讨论点击对seo排名的各种影响
- codeforces841E
- 欢迎使用CSDN-markdown编辑器
- 配置React Native的开发环境
- JavaSE 练习-File、字节流递归拷贝文件夹极其子文件夹和文件到目标文件夹中
- JAVA就业分析
- 运行异常:获取不到UI界面组件对象