给大家介绍7中js继承的方法

  有些人认为JavaScript并不是真正的面向对象语言,在经典的面向对象语言中,您可能倾向于定义类对象,然后您可以简单地定义哪些类继承哪些类(参考C++ inheritance里的一些简单的例子),JavaScript使用了另一套实现方式,继承的对象函数并不是通过复制而来,而是通过原型链继承

一、原型链继承

// 原型链实现继承
function Person(name,age) {
this.name=name;
this.age=age;
}
Person.prototype.show=function() {
console.log(`我是${this.name},我今年${this.age}`)
}
function Worker(name, age, job) {
Person.call(this, name, age);
this.job=job;
}
// 如果此处有Woker的原型对象上的方法,由于原型重定向,下面的代码会覆盖此方法
Worker.prototype = new Person();
// 应该写在此处
Worker.prototype.showJob=function() {
console.log(`我的工作是${this.job}`)
};
var mine = new Worker('佳', 18, '写代码');
console.log(mine);
mine.show();
mine.showJob();
存在的问题:
1.子类可以重写父类原型上的方法,Woker.prototype.__proto__.show=null, 此时已改变Person的原型对象上的方法;
2.父类的私有属性和公有属性都变成子类的公有属性;
3. 如果子类的原型对象上原本有属性和方法,Woker.prototype = new Person()后,之前的方法无法再获取到;
 
解释原型重定向:  Woker.prototype = new Person();
1.自己开辟的堆内存中没有constructor属性,导致类的原型构造函数缺失(解决:自己手动在堆内存中增加constructor属性)
2.当原型重定向后,浏览器默认开辟的那个原型堆内存会被释放掉,如果之前已经存储了一些方法或者属性,这些东西都会丢失(所以:内置类的原型不允许重定向到自己开辟的堆内存,因为内置类原型上自带很多属性方法,重定向后都没了,这样是不被允许的)
 

二、借用构造函数继承

function Person(name, age){
this.name=name;
this.age=age;
}
function Worker(name, age, job){
Person.call(this, name, age);
this.job=job;
}
var mine=new Worker('佳', 18, '写代码的');
console.log(mine);

优点:1. 相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向父类型构造函数传递参数。

缺点:1、只能继承父类构造函数的属性。

   2、无法实现构造函数的复用。(每次用每次都要重新调用)

   3、每个新实例都有父类构造函数的副本,臃肿。

三、组合继承(组合原型链继承和借用构造函数继承)(常用)

// 组合继承
function Person(name,age) {
this.name=name;
this.age=age;
}
Person.prototype.show=function() {
console.log(`我是${this.name},我今年${this.age}`)
}
function Worker(name, age, job) {
Person.call(this, name, age);
this.job=job;
}
Worker.prototype = new Person();
Worker.prototype.constructor = Worker;
Worker.prototype.showJob=function (){
console.log(`我的工作是${this.job}`)
};
var mine = new Worker('佳', 18, '打杂的');
console.log(mine);
mine.show();
mine.showJob();

重点:结合了两种模式的优点,传参和复用

优点:1、可以继承父类原型上的属性,可以传参,可复用。

   2、每个新实例引入的构造函数属性是私有的。

缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

四、原型式继承

// 原型式继承
function Woker(o){
function Empty(){};
Empty.prototype = o;
return new Empty();
}
var mine = {
name: 'jia',
age: 18,
job: '打杂的'
};
var anotherMine =Woker(mine);

重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。

特点:类似于复制一个对象,用函数来包装。

缺点:1、所有实例都会继承原型上的属性。

   2、无法实现复用。(新实例属性都是后面添加的)

var woker={
name: 'jia',
age: 18,
job: '打杂的'
}
var mine = Object.create(woker);

原理和上面相同,ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。

 Object.create:内置Object类天生自带的方法
1.创建一个空对象
 2.让新创建的空对象的__proto__指向第一个传递进来的对象(把传入的对象作为新创建空对象的原型)
 
五、寄生式继承
// 寄生式继承
function createAnother(o) {
var person = Woker(o);
person.show=function() {
console.log(`我是jia`)
}
return person;
}
var mine = {
name: 'jia',
age: 18,
job: '打杂的'
};
var anotherMine = createAnother(mine);

重点:就是给原型式继承外面套了个壳子。

优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。

缺点:没用到原型,无法复用。

也可用 Object.create()方法实现

六、寄生组合式继承

  //寄生组合式继承
function inheritProto(parents,child){
var o=Object.create(parents.prototype);
o.constructor=child;
child.prototype=o;
}
//父类构造函数
function Parents(surname){
this.surname=surname;
}
Parents.prototype.getSurname=function(){
console.log(this.surname);
}
//子类构造函数
function Child(surname,age){
Parents.call(this,surname);
this.age=age;
}
inheritProto(Parents,Child); Child.prototype.getAge=function(){
console.log(this.age);
}

寄生组合式继承,集寄生式继承和组合继承的优点与一身,是实现基于类型继承的最有效方式。YUI 的 YAHOO.lang.extend()方法采用了寄生组合继承,从而让这种模式首次 出现在了一个应用非常广泛的 JavaScript 库中。要了解有关 YUI 的更多信息,请访问 http://developer. yahoo.com/yui/。

七、ES6的Class实现继承

class Person{
constructor(name, age){
this.name=name;
this.age=age;
}
show(){
alert(this.name);
alert(this.age);
}
} class Worker extends Person{
constructor(name, age, job){
super(name, age);
this.job=job;
}
showJob(){
alert(this.job);
}
}
let me=new Worker('jia', 18, '前端攻城狮');
me.show();
me.showJob();

好啦,常见的7种JS继承的方法介绍完了。~~

深入浅出js实现继承的7种方式的更多相关文章

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

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

  2. js 实现继承的几种方式

    //js中实现继承的几种方式 //实现继承首先要有一个父类,先创造一个动物的父类 function Animal(name){ this.name = name; this.shoot = funct ...

  3. js 实现继承的6种方式(逐渐优化)

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  4. js实现继承的两种方式

    这是面试时面试官会经常问到问题: js的继承方式大致可分为两种:对象冒充和原型方式: 一.先说对象冒充,又可分为3种:临时属性方式.call().apply(): 1.临时属性方式: 当构造对象son ...

  5. js实现继承的5种方式

    js是门灵活的语言,实现一种功能往往有多种做法,ECMAScript没有明确的继承机制,而是通过模仿实现的,根据js语言的本身的特性,js实现继承有以下通用的几种方式1.使用对象冒充实现继承(该种实现 ...

  6. JS实现继承的几种方式

    前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一.那么如何在JS中实现继承呢?让我们拭目以待. JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如下: // 定义一个 ...

  7. JavaScript面向对象(三)——继承与闭包、JS实现继承的三种方式

      前  言 JRedu 在之前的两篇博客中,我们详细探讨了JavaScript OOP中的各种知识点(JS OOP基础与JS 中This指向详解 . 成员属性.静态属性.原型属性与JS原型链).今天 ...

  8. JS 面向对象 ~ 继承的7种方式

    前言: 继承 是 OO 语言中的一个最为人津津乐道的概念.许多 OO 语言都支持两种继承方式:接口继承 和 实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.如前所述,由于函数没有签名,在 ...

  9. JS实现继承的几种方式(转)

    转自:幻天芒的博客 前言 JS作为面向对象的弱类型语言,继承也是其非常强大的特性之一.那么如何在JS中实现继承呢?让我们拭目以待. JS继承的实现方式 既然要实现继承,那么首先我们得有一个父类,代码如 ...

随机推荐

  1. 计算机组成原理——DMA存取方式

    DMA(Direct Memory Access)直接存储器存取 高速大容量存储器和主存之间交换时,若采用程序直接传送或程序中断传送的方式,则会有如下问题发生.    1)采用程序直接传送,主机工作效 ...

  2. Java题库——Chapter8 对象和类

    1)________ represents an entity(实体) in the real world that can be distinctly identified. 1) _______ ...

  3. 多进程操作-进程队列multiprocess.Queue的使用

    一.ipc机制 进程通讯 管道:pipe 基于共享的内存空间 队列:pipe+锁 queue 下面拿代码来实现Queue如何使用: 案例一: from multiprocessing import Q ...

  4. 使用laravel-amdin调用文件上传阿里oss注意点

    开发者工作中,项目代码开发提高效率,往往会使用一些github上面的一些扩展类,这里举例说明一下遇到的情况. 一.使用laravel-admin框架开发管理后台文件或者图片上传 情景:运营或者产品通过 ...

  5. 每秒100W请求,12306秒杀业务,架构如何优化?

    如<同样是高并发,QQ/微博/12306的架构难度一样吗?>一文所述,同样是高并发场景,三类业务的架构挑战不一样: QQ类业务,用户主要读写自己的数据,访问基本带有uid属性,数据访问锁冲 ...

  6. JQuery Deferred对象使用小结

    场景描述 如下,打开页面时,获取默认选中的项目,同时也会初始化Combobox下拉框下拉列表数据 问题描述 获取默认选中项目及下拉列表的js函数位于common.js文件,类似如下: // 根据项目类 ...

  7. cookie --中间件

    Cookie简介 cookie是服务器存储在用户计算机中的变量,可以让我们用同一个浏览器访问同一个域名的时共享数据. HTTP是一种无状态协议,简单来说,当你从一个页面,然后跳转到同站点的另一个页面时 ...

  8. mysql登陆时出现ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

    有4到5天没开mysql,这天晚上打=打开phpstudy,想进去mysql练习练习,结果丢给我这个 ERROR 2013 (HY000): Lost connection to MySQL serv ...

  9. Android6.0 源码修改之Setting列表配置项动态添加和静态添加

    写在前面 最近客户有个需求,要求增加操作Setting列表配置项的功能,是不是一脸懵,没关系,一图胜千言,接下来就上图.诺,就是这么个意思.   原来的列表配置项     增加了单个配置项     增 ...

  10. iOS sqlite ORM框架-LKDBHelper

    LKDBHelper 一个sqlite ORM(全自动操作数据库)框架. 线程安全.不再担心递归锁死的问题 安装要求 iOS 4.3+ 仅支持 ARC FMDB 添加到你的项目 如果你使用 Cocoa ...