有关JS”类“的继承

    首先要说明:JS并没有类(class)的概念,本文只是用了"类"这个叫法,虽然说ES6开始有了类的概念,但是,ES6中的类,仅仅只是基于现有的原型继承的一种语法糖。

一、面向对象思想

   在这里我就只说说关于面向对象的一些基本知识:

  • 定义某一事物的抽象特点,具有属性和方法。简单的理解来说:类好比一个黑盒子,你不需要知道里面的功能,就可以使用它。举个栗子:一台空调,你只需要知道上面的按钮有什么用,就可以使用这台空调,完全不需要知道这台空调里面到底是怎么工作的。
  • 对象:类的一个实例。例如:var myDate = new Date();    //myDate就是通过new关键字,创建的一个对象。它就是系统中的"类":Date()的一个实例;
  • 属性:对象的特征;
  • 方法:对象的行为;
  • 封装性:只有特定类的对象才能访问特定类的成员;
  • 继承性:子类继承父类的属性和方法;
  • 多态性:不同的类可以定义相同的属性和方法;
  • 抽象性:(就是类这个概念很抽象咯,\滑稽)

二、类的属性和方法的继承

    纠正一下:由于JS并没有类(class)的概念,更多的时候我们把它叫做对象(function),然后把对象叫做实例(instance)出去和别人讨论oop时,一定要叫对一些概念的名字,免得贻笑大方。

在这里我就直接用类(class)这个叫法。

1、属性的继承:

  1.先来看一个小例子:

function show() {
    alert(this);
}
show();  //[object window]    //很显然输出window对象

  2.再来看一下:

function show() {
    alert(this);
}
show.call(123);  //123

这是因为函数调用call()方法时,第一个参数会覆盖函数中的this。也就是说,这里123this覆盖了。这是call()方法的一个用法。

有关call()的详尽使用大家可以自行百度,这里就不介绍了。


  3.继续介绍,刚步入正题:

function A() {
    this.aaa = 111;
}
var objA = new A();
alert(objA.aaa);  //111

通过类: A 创建一个对象: objA  ,所以对象: objA 就具有了aaa这个属性。

ps:这里的构造函数A,就相当于"类"。我们平时经常会用到"类",像:Array, Date... 等,这些都是系统内置的"类",我们叫它系统"类",而上面的A就是我们自己自定义的"类"。


  4.终于说到继承属性了:

function A() {
    this.aaa = 111;
}
function B() {
    A.call(this);
}
var objB = new B();               
alert(objB.aaa);  //111    //实现继承属性

解释一下:通过类: B 创建对象: objB 后,类: B 中的this指向objB,这时候A.call(this)就相当于A.call(objB),正如前面所说,objB会覆盖类: A 中的this,所以objB就具有了aaa属性,所以就实现了属性的继承。

2、方法的继承:

  1.简单的写法:

function A() {}
function B() {}

A.prototype.showA = function () {
    alert('aaa');  
};

B.prototype = A.prototype;

var objA = new A();
var objB = new B();

objB.showA();  //aaa    //证明 B 确实继承了 A 的方法

但是这种方法虽然简单,但是有个很大的缺陷,实际上:B.prototype 是对 A.prototype 的引用。

下面我们来证明这一点:在上述代码 B.prototype = A.prototype; 这行代码后面添加:

B.prototype.showB = function () {
    alert('bbb');
};

然后 objA.showB();    //bbb       //这就证明,B.prototype确实是对A.prototype的引用。

  2.避免引用

function A() {}
function B() {}

A.prototype.showA = function () {
    alert('aaa');
};

//用for...in...循环,将A的属性一一赋给B,这样就不会造成B.prototype对A.prototype引用
for (let i in A.prototype) {
    B.prototype[i] = A.prototype[i];
}
		
B.prototype.showB = function () {
    alert('bbb');
};
		
var objA = new A();
var objB = new B();

objB.showA();  //aaa    //证明B继承了A的方法
objA.showB();  //error    //证明A上并没有showB方法,说明A没有被引用

三、结语

因水平有限,文章有不足或错误,欢迎大家理性指正,一起进步哦!


本文用到的一些知识,知识储备不足的同学可以看看下面的这些文章(这几篇是我看过的,认为讲的很好的文章):

1. call() 和 apply() :https://juejin.im/entry/5b028bf9f265da0b814bdb33

2. 原型、原型链:https://mp.weixin.qq.com/s/WTiTCBmSmGYvjIjXWWh1DA

--------------------------------------------------------END--------------------------------------------------------------

本文参考文章:https://blog.csdn.net/alex8046/article/details/51940518

猜你喜欢

转载自blog.csdn.net/qq_41139830/article/details/80456407