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

常见六种继承方式:
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. leetcode 91. 解码方法

    题目描述: 一条包含字母 A-Z 的消息通过以下方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给定一个只包含数字的非空字符串,请计算解码方法的总数 ...

  2. 切换本地凭据(Windows上登录的GitHub账号)

    切换本地用户,可以向微软小娜搜索Windows凭据,这个步骤可以参考这篇博客 的说明.

  3. adb 调系统时间

    1.修改前提 获取系统root权限,然后adb shell进入shell界面 adb shell su 2.时区设置 cat /data/property/persist.sys.timezone / ...

  4. 判断两个IP地址是不是属于同一子网的方法

    一个IP地址有三种写法: 第一种,单个IP,如192.168.55.28 第二种,IP/子网掩码,如192.168.55.28/255.255.255.0 第三种,IP/子网掩码长度,如192.168 ...

  5. Unity GL 画圆

    Unity下GL没有画圆的函数,只能自己来了. 如果能帮到大家,我也很高兴. 虽然没有画圆的函数,但是能画直线,利用这一点,配合微积分什么的,就可以画出来了.反正就是花很多连在一起的直线,每条直线足够 ...

  6. 服务器部署nginx报错 nginx: [warn] conflicting server name "localhost" on xxx.xxx.xxx.xxx:80, ignored

    问题 修改nginx配置参数后,使用nginx -t检查配置. 提示successfull后就可以使用 nginx -s reload来重新加载配置 我配置的过程中遇到这样的问题,就是绑定了主机名后, ...

  7. svn报错cleanup failed–previous operation has not finished; run cleanup if it was interrupte...

    今天在svn提交的时候它卡顿了一下,我以为已经提交完了,就按了一下,结果就再也恢复不了,也继续不了了... 报错 cleanup failed–previous operation has not f ...

  8. C#语言使用习惯

    1.使用属性而不是可访问的数据成员 2.用运行时常量(readonly)而不是编译期常量(const) 编译期常量与运行时常量行为的不同之处在于对他们的访问方式不同,编译期常量的值是在目标代码中进行替 ...

  9. Java 在使用@Select遇到的问题:拼接字符串将数组拼为了字符串

    Java再用@Select拼接sql语句时候, #{参数名}:是加引号的 ${参数名}:是不加引号的 例如: userIds为List或者数组,值为1,2,3,4,5 1.@Select(" ...

  10. JQuery notepad

    ready:在文档加载后执行,在文档对象加载完毕后,页面完全显示后执行,把所有事件函数放在ready中加载是一种非常好的方法,ready() 函数不应与 <body onload="& ...