了解继承前我们需要了解函数的构造,方便我们理解。

常见六种继承方式:
1.原型继承call和apply;
2.原型拷贝:循环父函数protype的key值=子函数prototype的key值;
3.原型链继承:父函数实例继承给子函数prototype;
4.混合继承:父函数的protype=子函数的-proto-;
5.寄生继承:新建fn函数,其protype等于父函数protype实例,在将fn的实例等于子函数protype,加consuctor;
6.class类继承:consuctor的super方法;

一、call(),apply():


一般情况下 我们只会用call和apply实现属性的继承 不会实现方法的继承;
prototype:每一个函数都有一个prototyp属性 这个属性指向一个对象 这个对象叫做原型对象
原型对象里面有2个属性:constructor,__proto__   
 原型链:由__proto__组成的链条叫做原型链

一、它们各自的定义:

1.apply:
调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
2.call:
调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
二、它们的共同之处:

都以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。

三、它们的不同之处:
apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个
数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将
导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法
被传递任何参数。
call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法
相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,
那么 Global 对象被用作thisObj。 实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。*/
/*apply()方法*/
function.apply(thisObj[, argArray]);
/*call()方法*/
function.call(thisObj[, arg1[, arg2[, [, ...argN]]]]);
举例:

/*父类*/
function Parent(add, net, no, teacher) {
this.add = add;
this.net = net;
this.no = no;
this.teacher = teacher
}
/*子类*/
function Child(name, age, sex, id) {
this.name = name;
this.sex = sex;
this.age = age;
this.id = id;
Parent.call(this, "山东", "www.baidu.com", "1608", "ccy"); //这个时候的Parent中的this已经被Child
所代替
}
var child = new Child("fangMing", "18", "男", "10086");
console.log(child.add)
/*如果想用apply方法,可以将注释的一句改为Parent.apply(this,["山东","www.baidu.com","1608","ccy"]),
两者的用法是一样的等效,唯一的区别就是call后面跟的是有个一个一个单独的数据,而apply需要把数据放在数组里面*/

二、原型拷贝:

function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sleep = function () { }
Person.prototype.play = function () { }
Person.prototype.eat = function () {
console.log("1122")
}
var p1 = new Person()
function Man(beard, larynx, name, age, sex) {
Person.apply(this, [name, age, sex])
this.beard = beard;
this.larynx = larynx;
}
for (var key in Person.prototype) {
Man.prototype[key] = Person.prototype[key]
}
Man.prototype.work = function () { }
Man.prototype.eat = function () {
console.log('3344')
}
//实例化
, "很大", "陈亮", "40", "男");
console.log(chenliang)
console.log([Person])
chenliang.eat()
p1.eat();

三、原型链继承:

/*
原型链继承:实例化父函数,将其
实例

拷贝给子元素的prototype,这样就子函数继承了

了父函数中的方法了。
*/
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sleep = function () { }
Person.prototype.play = function () { }
Person.prototype.eat = function () {
console.log("1122")
}
var p1 = new Person()
function Man(beard, larynx, name, age, sex) {
Person.apply(this, [name, age, sex])
this.beard = beard;
this.larynx = larynx;
}
/*
1、多了很多无用的属性---->直接使用原型链继承的时候可能把属性和方法都继承过来了
用原型链继承的时候可能把属性放在了prototype上面
2、少了一个constructor
*/
Man.prototype = new Person();
Man.prototype.work = function () { }
//实例化
, "很大", "陈亮", "40", "男");
console.log(chenliang)
console.log(p1)

四、混合继承:

/*
混合继承:将父函数的prototype拷贝给子函数的_proto_
*/
//人类
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sleep = function () { }
Person.prototype.play = function () { }
Person.prototype.eat = function () {
console.log("1122")
}
var p1 = new Person()
//p1.__proto__:原型对象 == Person.prototype 原型对象
function Man(beard, larynx, name, age, sex) {
Person.apply(this, [name, age, sex])
this.beard = beard;
this.larynx = larynx;
}
/*
1、多了很多无用的属性
2、少了一个constructor
*/
Man.prototype = {
constructor: Man,
__proto__: Person.prototype
}
Man.prototype.work = function () { }
//实例化
, "很大", "陈亮", "40", "男");
console.log(chenliang)
console.log(p1)

>五、寄生继承

/*
寄生继承:创建一个空fn函数,将父函数的prototype拷贝给fn.prototype;
然后将子函数的prototype拷贝fn函数的实例,给子函数加一个constructor指向子函数;
*/
//人类
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
Person.prototype.sleep = function () { }
Person.prototype.play = function () { }
Person.prototype.eat = function () {
console.log("1122")
}
var p1 = new Person()
function Man(beard, larynx, name, age, sex) {
Person.apply(this, [name, age, sex])
this.beard = beard;
this.larynx = larynx;
}
/*
1、多了很多无用的属性
2、少了一个constructor
*/
function fn() { }
fn.prototype = Person.prototype;
//原型链继承
Man.prototype = new fn();
Man.prototype.constructor = Man;
Man.prototype.work = function () { }
//实例化
, "很大", "陈亮", "40", "男");
console.log(chenliang)
console.log(p1)

>六、Class类继承

class Person{
//属性
constructor(name,age){
this.name = name;
this.age = age;
}
eat(){
console.log('111')
}
show(){
console.log('222')
}
}
//ES6的继承
class Man extends Person{
constructor(beard,name,age){
super(name,age)
this.beard = beard;
}
work(){}
}
,);
console.log(p2)

深入浅出:了解JavaScript的六种继承的更多相关文章

  1. JavaScript的六种继承方式

    继承是面向对象编程中又一非常重要的概念,JavaScript支持实现继承,不支持接口继承,实现继承主要依靠原型链来实现的 原型链 首先得要明白什么是原型链,在一篇文章看懂proto和prototype ...

  2. JavaScript 常见的六种继承方式

    JavaScript 常见的六种继承方式 前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分 ...

  3. JavaScript 六种继承方式

    title: JS的六种继承方式 date: 2017-06-27 05:55:49 tags: JS categories: 学习 --- 继承是面向对象编程中又一非常重要的概念,JavaScrip ...

  4. JavaScript常见的六种继承方式

    前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...

  5. JavaScript常用,继承,原生JavaScript实现classList

    原文链接:http://caibaojian.com/8-javascript-attention.html 基于 Class 的组件最佳实践(Class Based Components) 基于 C ...

  6. 浅谈 JavaScript 中的继承模式

    最近在读一本设计模式的书,书中的开头部分就讲了一下 JavaScript 中的继承,阅读之后写下了这篇博客作为笔记.毕竟好记性不如烂笔头. JavaScript 是一门面向对象的语言,但是 ES6 之 ...

  7. javascript 之 prototype继承机制

    理解Javascript语言的继承机制 javascript没有"子类"和"父类"的概念,也没有"类"(class)和"实例&qu ...

  8. JavaScript寄生组合式继承分析

    JavaScript寄生组合式继承特点: 避免了在子类prototype上创建不必要多余的属性,相比直接继承基类的实例效率要高. 是JavaScript 实现继承的最有效方式. <script& ...

  9. 深入理解:JavaScript原型与继承

    深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解. 首先JavaScr ...

随机推荐

  1. C语言的头文件和宏定义详解

    原文链接:https://blog.csdn.net/abc_12366/article/details/79155540

  2. redis结合springboot 无法注入redisTemplate问题

    报错: Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean o ...

  3. Unity [Tooltip("")]

    把Ad2Controller脚本挂在Ad2Ad3Manager游戏对象上,在非运行状态下把鼠标放在inspector的AdButtonObj2上就会显示广告2按钮. 如下图:

  4. Linux中vim编辑器的缩进的功能键

    vim编程时,经常需要对代码进行缩进处理,以增加程序的可读性和后期的代码维护. 可以采用多种方式达到缩进的目的: 1) 命令模式(command mode) 2) Visual模式(visual mo ...

  5. Storm概念学习系列之storm简介

    不多说,直接上干货! storm简介 Storm 是 Twitter 开源的.分布式的.容错的实时计算系统,遵循 Eclipse Public License1.0. Storm 通过简单的 API ...

  6. Hibernate的工作流程以及三种状态(面试题)

    Hibernate的工作流程以及三种状态 部分转载自:http://www.cnblogs.com/fifiyong/p/6390699.html Hibernate的工作流程: 1. 读取并解析配置 ...

  7. git 使用流程 命令

    克隆远程分支到本地 git clone <https://github.com/cqzyl/methods.js.git> 进入master分支 git checkout master 以 ...

  8. jquery初始

    今天我们来学习Jquery的一些基本知识,jquery相对来说还是比较重要的,所以还是要好好学习的. 首先要了解什么是jQuery? l类似于python里面的模块,可以看成是一种库或者插件. 在学习 ...

  9. vue列表到详情页的实现

    路由里边的 router/index.js path:'/detail/:id' 动态id 列表页渲染时: :to="'/detail/'+item.id" ===>id是指 ...

  10. JAVA中日期格式转换各个字母代表含义

    G  Era 标志符  Text  AD  y  年  Year  1996; 96  M  年中的月份  Month  July; Jul; 07  w  年中的周数  Number  27  W  ...