关于JS继承

关于继承这个概念,是由面向对象衍生出来的。而JS身为一种基于面向对象而设计的语言,它和正统的面向对象语言又是有差别的。

面向对象语言

身为面向对象语言需要对开发者提供四种能力:

①:封装 - 把相关的信息(无论数据或方法)存储在对象中的能力;

②:聚集 - 把一个对象存储在另一个对象内的能力;

③:多态 - 编写能以多种方法运行的函数或方法的能力;

④:继承 - 有另一个或多个类得来类的属性和方法的能力;

虽然JS都具备这种能力,然而它却和正统的面向对象语言有差异,具体表现主要在第③、④点。

多态

多态主要有两种实现形式:

①:重载(编译时多态性) - 方法名相同,形参个数或类型不同;

②:重写(运行时多态性) - 在继承中,子类重写父类的方法;

这两种形式上JS和java/C#是表现形式是不一样的。

重载:

// java代码示例
public void sum(int n, float m){ }
public void sum(int n, float m, int t){ }
public void sum(int n, float m, String t){ }

在java中这sum方法会分别在不同情况下调用。

// js代码示例
function sum(n,m){ }
function sum(n,m,t){ }

在JS中sum方法在前面定义的会被后面定义的覆盖,因此JS用相同方法处理不用情况只能在sum方法内部对数据做识别判断了。

重写:

//java代码示例
public class Main { public static void main(String[] args) {
Student a = new Student();
a.say();
}
} class person{
public void say(){
System.out.println("11111");
}
} class Student extends person{
public void say(){
System.out.println("22222");
}
}

这里Student继承了person,对say方法进行了重写,虽然重写了say方法,但是父类方法不会被改变。

//js代码示例
function A(m){
this.m = m;
}
A.prototype.getM = function(){
console.log(100,this.m)
} function B(n){
this.n = n;
}
B.prototype = new A(100);
B.prototype.getN = function(){
console.log(this.n)
} let b = new B(200);
b.getM(); //打印 100,100 b.getM = function(){
console.log(1)
}
b.getM(); //打印 1
A.prototype.getM(); //打印 100,undefined b.__proto__.__proto__.getM = function(){
console.log(0,this.m)
};
b.getM(); //打印 1
A.prototype.getM(); //打印 0,undefined

而JS对继承的父类的重写就有点不一样了,JS是基于原型链的继承。调用方法或对象时会在原型链中追溯,而当在实例b中添加了getM方法时,其实是拦截了原型链上的getM,因此这种拦截不会改动到A.prototype.getM,然而A.prototype.getM又不是绝对的私密的,在示例中可以看到利用b.__proto__.__proto__.getM重写getM是会导致A.prototype.getM也被重写的,所以js原型链继承中是没有完整意义上的私密属性的。

继承

和其他正统的面向对象语言不一样,其他语言的继承一般都是拷贝继承,也就是子类会把父类中的方法和属性拷贝的子类中实现继承,而JS的继承是把父类的原型放在子类的原型链上,利用原型链的查找机制实现继承的。

而且JS的继承方式也是很多的,下面列举一下比较常见的继承方式。

一、原型链继承
function A(m){
this.m = m;
}
A.prototype.getM = function(){
console.log(this.m)
} function B(n){
this.n = n;
}
B.prototype = new A(100);
B.prototype.getN = function(){
console.log(this.n)
} let b = new B(200);
b.getN(); //输出 200
b.getM(); //输出 100

特点:

1、非常纯粹的继承关系,实例是子类的实例,也是父类的实例;

2、父类新增属性或其原型新增属性,子类都能访问;

缺点:

1、子类能重写父类方法,如:b.__proto__.__proto__.getM = null,可以改写父类方法;

2、父类的私有属性和公有属性都变成子类的公有属性;

3、继承时方法B原型上原有的方法或属性会丢失,如:constructor构造函数;(解决:B.prototype = B);

4、子类创建实例时无法向父类传参;

5、无法实现多继承;

二、构造函数继承
function A(m, n){
this.m=m;
this.n=n;
}
function B(m, n, t){
A.call(this, m, n);
this.t=t;
}
var b = new B(1, 2, 3);
console.log(b.m, b.n, b.t);

特点:

1、能在子类创建实例时向父类传递参数;

2、可以实现多继承;

缺点:

1、只能继承父类的属性(不继承原型链);

2、创建的实例携带着父类属性,臃肿;

三、寄生组合继承
function B(n){
this.n = n;
}
B.prototype.getB = function(name){
console.log(this.n, name);
} function A(m){
B.call(this,200)
this.m = m;
} // 我是旧时代的残党,新时代没有适合承载我的船
// (function(){
// // 创建一个没有实例方法的类
// var Super = function(){};
// Super.prototype = B.prototype;
// //将实例作为子类的原型
// A.prototype = new Super();
// })(); // ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。
A.prototype = Object.create(B.prototype); A.prototype.constructor = A;
A.prototype.getA = function(name){
console.log(this.m, name)
} var aa = new A(100);
aa.getA("A");
aa.getB("B");

特点:

1、可以继承父类的属性及其原型上的属性;

2、既是子类的实例,也是父类的实例;

3、不存在引用属性共享问题;

4、父类可接收传参;

关于JS继承的更多相关文章

  1. js继承

    js继承有5种实现方式: 继承第一种方式:对象冒充 function Parent(username){ this.username = username; this.hello = function ...

  2. js继承之call,apply和prototype随谈

    在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...

  3. js继承精益求精之寄生式组合继承

    一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...

  4. 老生常谈--Js继承小结

    一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.net/stoy ...

  5. Js继承小结

    Js继承小结 一直以来,对Js的继承有所认识,但是认识不全面,没什么深刻印象.于是,经常性的浪费很多时间重新看博文学习继承,今天工作不是特别忙,有幸看到了http://www.slideshare.n ...

  6. js继承实现

    JS实现继承可以分为:对象冒充和原型链继承 其中对象冒充又包括:临时变量,call 和 apply 临时变量方法: function Person(name,sex){ this.name = nam ...

  7. js继承之借用构造函数继承

    我的上一篇文章介绍了,原型链继承模式.但是单纯的原型链模式并不能很好地实现继承. 一.原型链的缺点 1.1 单纯的原型链继承最大的一个缺点,来自于原型中包含引用类型的值. 本来,我们没有通过原型链实现 ...

  8. js继承之原型链继承

    面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...

  9. js继承的常用方法

    写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...

  10. JS--我发现,原来你是这样的JS:面向对象编程OOP[3]--(JS继承)

    一.面向对象编程(继承) 这篇博客是面向对象编程的第三篇,JS继承.继承顾名思义,就是获取父辈的各种"财产"(属性和方法). 怎么实现继承? 我们的JavaScript比较特别了, ...

随机推荐

  1. go面试题-基础类

    go基础类 1. go优势 * 天生支持并发,性能高 * 单一的标准代码格式,比其它语言更具可读性 * 自动垃圾收集比java和python更有效,因为它与程序同时执行 go数据类型 int stri ...

  2. 『无为则无心』Python函数 — 38、Python中的异常

    目录 1.异常概念 2.了解异常 3.异常的写法 (1)语法 (2)快速体验 (3)捕获指定异常 (4)异常中的else (5)异常中的finally (6)总结 1.异常概念 定义:程序在运行过程当 ...

  3. 推荐召回--基于内容的召回:Content Based

    目录 1. 前言 2. 构建画像 3. 内容召回的算法 1. 前言 在之前总结过协同过滤的召回通路后,今天我们来总结下召回策略中的重头戏:基于内容的召回通路,也即我们常说的基于标签的召回.这里就要涉及 ...

  4. 安卓开发常见Bug-setContentView(R.layout.....)报错

    这是安卓开发的常见错误,当你在引用或者复制别人的Layout xml文件时需要在AndroidManifest.xml中添加东西 需要将图中的activity android:name添加进去,否则是 ...

  5. java中的继承 和多态。

    package com.aaa.zxf.ajax.test; /** *一. java 中的继承和多态. * * 继承的特性? * 1.实现继承的方式 * A 如何建立继承关系(一个类继承于 另一个类 ...

  6. 布客·ApacheCN 翻译校对活动进度公告 2020.5

    注意 请贡献者查看参与方式,然后直接在 ISSUE 中认领. 翻译/校对三个文档就可以申请当负责人,我们会把你拉进合伙人群.翻译/校对五个文档的贡献者,可以申请实习证明. 请私聊片刻(52981514 ...

  7. 微服务架构 | 11.1 整合 Seata AT 模式实现分布式事务

    目录 前言 1. Seata 基础知识 1.1 Seata 的 AT 模式 1.2 Seata AT 模式的工作流程 1.3 Seata 服务端的存储模式 1.4 Seata 与 Spring Clo ...

  8. ARP数据包分析

    转载请注明来源:https://www.cnblogs.com/hookjc/ 本机IP:192.168.0.1 (c0 a8 00 01)本机MAC:00-50-56-c0-00-01目标IP:19 ...

  9. HDOJ acm steps 3.1.1

    (都是递推求值,呵呵,好开心- - ) 今天又是在自习室通宵(文明玩的停不下来了) 游戏玩完想想该水题了,于是打开了HDOJ的ACM STEPS(这是个好东西,就像他的名字,一步步来的) 2.3.x貌 ...

  10. C++ 反汇编:关于函数调用约定

    函数是任何一门高级语言中必须要存在的,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想的精髓,今天我将带大家一起来探索函数的实现机理,探索编译器到底是如何对函数这个关键字进行实现的,并使用 ...