这一章节主要说的是类与实例(包括类的声明、生成实例),类与继承(包括如何继承、继承的几种方式)
一、类的声明
/**
* 类的声明
* */
function Animal (){
this.name = 'name1'
}
/**
* ES6中class的声明
* */
class Animal2 {
constructor () {
this.name = 'name2'
}
}
二、类的实例化
console.log(new Animal(), new Animal2())
三、类与继承的几种方式(主要是ES5的)
1.继承方案1:将父亲的对象指向孩子
关键代码:Parent1.call(this)
function Parent1(){
this.name = 'parent1'
this.play = [1,2,3]
}
function Child1(){
Parent1.call(this)// 关键代码
this.type = 'child1'
}
// this指向不同的实例
var s1 = new Child1()
// console.log(s1.play)
缺点:如果父类属性都在父类里则没有问题,如果父类的原型还有方法时,那么子类无法继承父类原型上的方法。
2.继承方案2:借助原型链的方法继承
关键代码:Child2.prototype = new Parent2()
function Parent2(){
this.name = 'parent2'
this.play = [1,2,3]
}
function Child2(){
this.type = 'child2'
}
Child2.prototype = new Parent2()
var s2 = new Child2()
var s3 = new Child2()
s2.play.push(4,5)
console.log(s2.play, s3.play)//[1, 2, 3, 4, 5] (5) [1, 2, 3, 4, 5]这个不是想要看到的
缺点:原型上面的方法时共用的,实例改变值,那么其他的实例也会被改变,这个违背了继承的本质
3.组合继承优化方案一:结合上面1,2
关键代码:Parent3.call(this);Child3.prototype = new Parent3();
function Parent3(){
this.name = 'paren3'
this.play = [1,2,3]
}
function Child3(){// 这里为第2次
Parent3.call(this)
this.type = 'child3'
}
Child3.prototype = new Parent3()// 这里1次
var s4 = new Child3()
var s5 = new Child3()
s4.play.push(4,5)
// console.log(s4.play, s5.play)
缺点:父类的构造函数执行了两次
4.组合继承优化方案二:
关键代码:Child4.prototype = Parent4.prototype
function Parent4(){
this.name = 'parent4';
this.play = [1,2,3];
}
function Child4(){
Parent4.call(this);
this.type = 'child4'
}
// 这个把Parent4的原型对象上的构造器也继承了
Child4.prototype = Parent4.prototype
// 下面这句是不能写在这里的,因为他们引用的是一个地址
// Child4.prototype.constructor = Child4
var s6 = new Child4();
var sp1 = new Parent4()
console.log(s6 instanceof Child4, s6 instanceof Parent4)
console.log(s6.constructor, sp1.constructor)
缺点:缺点时父类的constructor也被继承了
5.组合继承优化3:采用Object.create()中间件
function Parent5(){
this.name = 'parent5';
this.play = [1,2,3];
}
function Child5(){
Parent5.call(this);
this.type = 'child5'
}
// 通过Object.create()作为中间物体,将两个构造函数的原型对象上的构造器分开
// 参数是该对象的原型对象,然后把子类的构造函数赋值为该子类
Child5.prototype = Object.create(Parent5.prototype)// 可以通过__proto__去验证
// 如果没有这句话,child5依旧会往上面找到Paren5.prototype
Child5.prototype.constructor = Child5
var s7 = new Child5()
var sp2 = new Parent5()
console.log(s7 instanceof Child5, s7 instanceof Parent5)
console.log(s7.constructor, sp2.constructor)
这种方法还是比较完美的,我们再看下这个原理图,它采用的是Object.create()中间件将两个原型对象分离开。
Child5.prototype.__proto__ === Object.create(Parent5.prototype).__proto__
返回true
6.ES6继承方式
几乎与这种类似,ES6就不在这里说明了,具体看文档,还是比较简单的,文档链接https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/extends。采用extends继承。