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

常见六种继承方式:
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的六种继承方式
继承是面向对象编程中又一非常重要的概念,JavaScript支持实现继承,不支持接口继承,实现继承主要依靠原型链来实现的 原型链 首先得要明白什么是原型链,在一篇文章看懂proto和prototype ...
- JavaScript 常见的六种继承方式
JavaScript 常见的六种继承方式 前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分 ...
- JavaScript 六种继承方式
title: JS的六种继承方式 date: 2017-06-27 05:55:49 tags: JS categories: 学习 --- 继承是面向对象编程中又一非常重要的概念,JavaScrip ...
- JavaScript常见的六种继承方式
前言 面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过"类 ...
- JavaScript常用,继承,原生JavaScript实现classList
原文链接:http://caibaojian.com/8-javascript-attention.html 基于 Class 的组件最佳实践(Class Based Components) 基于 C ...
- 浅谈 JavaScript 中的继承模式
最近在读一本设计模式的书,书中的开头部分就讲了一下 JavaScript 中的继承,阅读之后写下了这篇博客作为笔记.毕竟好记性不如烂笔头. JavaScript 是一门面向对象的语言,但是 ES6 之 ...
- javascript 之 prototype继承机制
理解Javascript语言的继承机制 javascript没有"子类"和"父类"的概念,也没有"类"(class)和"实例&qu ...
- JavaScript寄生组合式继承分析
JavaScript寄生组合式继承特点: 避免了在子类prototype上创建不必要多余的属性,相比直接继承基类的实例效率要高. 是JavaScript 实现继承的最有效方式. <script& ...
- 深入理解:JavaScript原型与继承
深入理解:JavaScript原型与继承 看过不少书籍,不少文章,对于原型与继承的说明基本上让人不明觉厉,特别是对于习惯了面向对象编程的人来说更难理解,这里我就给大家说说我的理解. 首先JavaScr ...
随机推荐
- [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树
树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...
- 关于JS的Date对象的探究
一次代码审核,其中刚好遇见了一些知识点~记录顺带整理一下吧~ date对象是javascript语言中内置的数据类型,用于提供日期和时间的操作接口. Date类型使用自UTC1970年1月1日0点开始 ...
- linux开机出现Give root password for maintenance (or type Control-D to continue):解决办法
修改rc.local后导致 linux开机出现Give root password for maintenance,而且很多系统文件无法修改,之前的rc.local也不能修改了,单用户模式也无法进入 ...
- mybatis批量处理sql
转载大神 https://www.cnblogs.com/xujingyang/p/8301130.html
- java资料
HTML5+CSS3视频教程:http://pan.baidu.com/s/1hsyOjze 密码:c3uw JavaScript视频教程:链接:http://pan.baidu.com/s/1 ...
- 联想电脑Fn+F6禁用触摸板功能不管用
我的原因是电脑没有安装触摸板驱动,解决方法:去联想官网根据自己的主机编号下载适合自己的触摸板驱动,安装重启即可解决
- Unity MonoBehaviour.Invoke 调用
使用 Invoke() 方法需要注意 3点: 1 :它应该在 脚本的生命周期里的(Start.Update.OnGUI.FixedUpdate.LateUpdate)中被调用: 2:Invoke(); ...
- (转)linux命令总结之ip命令
linux命令总结之ip命令 原文:https://www.cnblogs.com/ginvip/p/6367803.html linux命令总结之ip命令 Linux的ip命令和ifconfig ...
- Windows安全认证是如何进行的?[Kerberos篇]
最近一段时间都在折腾安全(Security)方面的东西,比如Windows认证.非对称加密.数字证书.数字签名.TLS/SSL.WS-Security等.如果时间允许,我很乐意写一系列的文章与广大网友 ...
- OracleJDK与OpenJDK的区别和联系
OpenJDK原是SunMicrosystems公司为Java平台构建的Java开发环境(JDK)的开源版本,完全自由,开放源码.OracleJDK里面包含的JVM是HotSpotVM,HotSpot ...