咱们知道,JS中没有类或接口的概念,即不能直接定义抽象的类,也不能直接实现继承。不过,为了编程的方便,咱们能够在 JS 中模拟类和继承的行为。
首先捋清楚类和对象的关系:编程
类:好比人类,指的是一个范围; 对象:好比某我的,指的是这个范围中具体的对象
js中的function做为构造函数时,就是一个类,经过new操做符,能够返回一个对象。app
类的声明:函数
第一种:传统构造函数声明
function Animal(){ this.name = 'tiger' }
第二种:ES6中的class声明
class Animal{ constructor(){ this.name = 'tiger' } }
生成实例:
虽然类的声明有多种方式不尽相同,可是类生成实例相同this
new Animal, new Animal2 // 没有参数时候 ()能够省略
类的继承的2种方式(主要说明es5传统构造函数的方式):es5
第一种:借助构造函数实现继承
<script> function Tiger(){ this.game = 'ow'; } Tiger.prototype.code=function(){ console.log('code M'); } function Child1(){ // <将构造函数Tiger的this指向子级构造函数child1的实例上> Tiger.call(this); this.type = 'child' } console.log(new Child1); </script>
原理
子类继承父类,经过call/apply改变父类构造函数的this指向prototype
缺点
只实现了部分继承,仅继承了父类的属性,并无继承父类的原型对象上<原型链上>的方法code
第二种:借助原型链实现继承
<script> function Funky(){ this.friend = 'Pite'; this.arr = [1,2,3]; } Funky.prototype.dance = function(){ console.log('let us dance!!!'); } function Child2(){ this.work = 'coder'; } Child2.prototype = new Funky(); //new Child2().__proto__ === new Parent2() console.log(new Child2); var a1 = new Child2; var a2 = new Child2; a1.arr.push('666'); // 此处更改a1的arr,a2的arr也会跟着改变 console.log(a1,a2); </script>
原理
经过继承__proto__实现原型链继承:对象
1 在当前Child2实例上查找dance方法
2 发现没有 就会去 proto 上面去找dance方法
3 Child2实例的 proto === Parent2实例
4 去Parent2实例上查找dance方法 发现没有
5 去Parent2实例的 proto 查找dance方法
6 找到。继承
缺点
若是实例两个对象 改变其中一个对象的属性/方法 另外一个对象也会跟着改变(由于改变的是原型链)接口