首先要说明: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。也就是说,这里123把this覆盖了。这是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