JS实现继承 JavaScript

定义一个父类:


// 定义一个动物类
function Animal (name) {
// 属性
this.name = name || ‘Animal’;
// 实例方法
this.sleep = function(){
console.log(this.name + ‘正在睡觉!’);
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + ‘正在吃:’ + food);
};

1.原型链继承

核心:将父类的实例作为子类的原型,JavaScript常见的六种继承方式


function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = ‘cat’; // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat(‘fish’));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

特点:

  1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
  2. 父类新增的原型方法、属性,子类都能访问到
  3. 简单,易于实现

缺点:

  1. 要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行(可以在cat构造函数中,为Cat实例增加实例属性)
  2. 无法实现多继承
  3. 来自原型对象的引用属性被所有实例共享
  4. 创建子类实例时,无法向父类构造函数传参

下面代码解释缺点3(注意是引用属性):


function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心 var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1 alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2

2.构造继承

核心:使用父类的构建函数来增强子类实例,等于复制父类的实例属性给子类(没用到原型),除了call方法,也可以用apply()


function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

  1. 解决了1中,子类实例共享父类引用属性的问题
  2. 创建子类实例时,可以向父类传递参数
  3. 可以实现多继承(call多个父类对象)

缺点:

  1. 实例并不是父类的实例,只是子类的实例
  2. 只能继承父类的实例属性和方法,不能继承原型属性和方法
  3. 无法实现函数复用,每个子类都有父类的实例函数的副本,影响性能

3.实例继承

核心:为父类实例添加新特性,作为子类实例返回


function Cat(name){
var instance = new Animal();
instance.name = name || ‘Tom’;
return instance;
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false

特点:

  1. 不限制调用方式,不管是new 子类()还是子类(),返回的对象都具有相同的效果

缺点:

  1. 实例是父类的实例,不是子类的实例
  2. 不支持多继承

4. 拷贝继承

核心:使用for...in将父类实例中的方法赋给子类实例


function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || ‘Tom’;
} // Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

特点:

  1. 支持多继承

缺点:

  1. 效率较低,内存占用高(因为要拷贝父类的属性)
  2. 无法获取父类不可枚举的方法(for in无法访问不可枚举的方法)

5.组合继承

核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用


function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
}
Cat.prototype = new Animal(); //组合继承需要修复构造函数的指向
Cat.prototype.constructor=Cat;
// Test Code var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

特点:

  1. 弥补了方式2的缺陷,可以继承实例属性、方法,也可以继承原型属性、方法
  2. 既是子类的实例,也是父类的实例
  3. 不存在引用属性的共享问题
  4. 可传参
  5. 函数可复用

缺点:

  1. 调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

6.寄生组合继承

核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点


function Cat(name){
Animal.call(this);
this.name = name || ‘Tom’;
}
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
//寄生组合继承需要修复构造函数的指向
Cat.prototype.constructor=Cat;
})(); // Test Code var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

特点:

  1. 堪称完美

缺点:

  1. 实现较为复杂

补充:es6的class实现继承


class Animal {
//构造函数
constructor(props) {
this.name = props.name || '未知';
} eat() {
alert(this.name + "在吃东西...");
}
} //class继承
class Bird extends Animal {
//构造函数
constructor(props) {
//调用实现父类的构造函数
super(props);
this.name = props.name || "未知";
} fly() {
alert(this.name + "在飞...");
}
}
var myBird = new Bird({
name: '鹦鹉'
})
myBird.eat() // 鹦鹉在吃东西...
myBird.fly() // 鹦鹉在飞...

来源:https://segmentfault.com/a/1190000017935023

JS实现继承 JavaScript的更多相关文章

  1. JS对象继承篇

    JS对象继承篇 ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现的 原型链 其基本思路是利用原型让一个引用类型继承另一个引用类型的属性和方法 function Person() ...

  2. JS类继承常用方式发展史

    JS类继承常用方式发展史 涉及知识点 构造函数方式继承 1-继承单个对象 1.1 多步走初始版 1.2 多步走优化版 1.3 Object.create()方式 2-继承多个对象 2.1 遍历 Obj ...

  3. JS原型继承与类的继承

    我们先看JS类的继承 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  4. 从 prototype.js 深入学习 javascript 的面向对象特性

    从 prototype.js 深入学习 javascript 的面向对象特性 js是一门很强大的语言,灵活,方便. 目前我接触到的语言当中,从语法角度上讲,只有 Ruby 比它更爽. 不过我接触的动态 ...

  5. 浅谈js中继承的理解和实现

    一.前言 java.C#等正统面向对象语言都会提供类似extend之类的处理类的继承的方法,而javascript并没有提供专门的方法用于继承,在javascript中使用继承需要一点技巧.js中实例 ...

  6. js各种继承方式和优缺点的介绍

    js各种继承方式和优缺点的介绍 作者: default 参考网址2 写在前面 本文讲解JavaScript各种继承方式和优缺点. 注意: 跟<JavaScript深入之创建对象>一样,更像 ...

  7. js的继承操作案例

    js的继承操作案例 一.总结 1.要案例要求,内心中想出操作要点 二.js的继承操作案例 案例 练习1:具有默认值的构造函数 实例描述: 有时候在创建对象时候,我们希望某些属性具有默认值 案例思路: ...

  8. js实现继承的5种方式 (笔记)

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

  9. js实现继承的方式总结

    js实现继承的5种方式 以下 均为 ES5 的写法: js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承 ...

随机推荐

  1. RocketMQ读书笔记1——简述

    [消息队列的功能介绍] 分布式消息队列可以提供应用解耦.流量削峰.消息分发.保证最终一致性.方便动态扩容等功能. [MQ使用场景1——应用解耦] 复杂的系统如电商系统,会存在多个子系统,如订单系统.库 ...

  2. <meta name="renderer" content="webkit">

    <meta name="renderer" content="webkit"> 当前国内的大部分主流浏览器(如360)基本都是双核浏览器,所谓双核即 ...

  3. android的系统设置界面

    Intent 的 意图: Intent intent = new Inetnt(Setings); Setings:   1. ACTION_ACCESSIBILITY_SETTINGS : // 跳 ...

  4. 使用intellij idea搭建MAVEN+SSM(Spring+SpringMVC+MyBatis)框架

    基本概念 使用SSM(Spring,SpringMVC和Mybatis) 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod  ...

  5. JavaWeb笔记——MVC设计模式和JavaWeb经典三层架

    1 MVC设计模式 MVC设计模式 MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(C ...

  6. 【Asp.Net MVC】asp.net mvc Model验证总结及常用正则表达式

    转自:http://www.cnblogs.com/easy5weikai/p/3843131.html 关于Model验证官方资料: http://msdn.microsoft.com/zh-cn/ ...

  7. 2017U-Mail邮件营销平台新邮件模板功能

    据U-Mail调查表明,企业用户中普遍最关心群发邮件会不会被列入垃圾箱?的确,哪怕你最用功,一旦邮件进了垃圾箱,意味着全盘尽废.业界知名服务商U-Mail一直想用户之所想,急用户之所急,十几年如一日, ...

  8. Redis客户端 Spring Data Redis(未完)

    官网:http://projects.spring.io/spring-data-redis/ 1.0  参考之前的一片文章:Gradle入门实战(Windows版) 构建java applicati ...

  9. Cacti监控mysql数据库server实现过程

    前言:cactiserver端安装请參考:http://blog.csdn.net/mchdba/article/details/27120605 1 先在cactiserver端安装mysql模板 ...

  10. js获取昨天今天和明天

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/UP19910522/article/details/30028299 <html> &l ...