面试准备 面向对象

类的声明两种写法

1.传统方式 :构造函数模拟类

function Animal() {
this.name = "name"
}  //生成动物类  通过this表示这是一个构造函数

2.ES6 中类的声明

class Animal {
    constructor () {  //构造函数
    this.name = name
}
} //es6增加了对类的声明,用class语法

如何实例化类的一个对象

new操作符 (如果构造函数没有传入参数,可以不加括号)

a1 = new Animal

类的继承

实现继承的基本原理: 原型链

问: 继承的方式有几种? 不同点?

1.借助构造函数实现继承

function Parent1() {
    this.name = "parent1"
}

function Child1() {
    Parent1.call(this)   //改变函数运行的上下文
    this.type = "child1"
}
//父级的构造函数 在子函数中执行。同时修改父级构造函数的this指向
指向了Child1类实例化后的实例。 

//有父类的属性 便实现了继承

 

问题:构造函数是有自己的原型链。任何一个函数都有prototype属性,

只有作为构造函数的时候

才能起到它的作用。这个方式的继承,导致父类的原型链并没有被继承

Parent1.prototype.say = function() {}   Child1的实例上并没有这个方法

所以只实现了部分继承。

2.借助原型链实现继承

function Parent2() {
this.name = "Parent2"
this.play = [1, 2, 3]//一个类上实例两个对象,修改一个对象,另一个对象也发生改变
因为原型对象是公用的
} function Child2() { this.type = "Child2" } Child2.prototype = new Parent2() //按照作用域的寻找方式 先找子元素,再往上找就是父类,就实现了继承

缺点:

一个类上实例两个对象,修改一个对象,另一个对象也发生改变
因为原型对象是公用的



 3.原型和构造函数的组合方式

function Parent3() {
this.name = "Parent3"
this.play = [1, 2, 3]
}

function Child3() {
Parent3.call(this)
this.type = "Child3"
}
Child3.prototype = new Parent3() //面向对象写继承最通用的方式 直接拿父类的实例,该例子没有
自己的constrctor。是从父类继承的

缺点:创建实例的时候 父类构造函数执行了两次

缺点2: 子类创建的实例 是父类的实例 new child3().constrctor === Parent3

4.优化1

function Parent4() {
this.name = "Parent4"
this.play = [1, 2, 3]
}

function Child4() {
Parent4.call(this)
this.type = "Child4"
}
Child4.prototype = Parent4.prototype//两个构造函数组合,
已经能拿到所有构造函数内的属性和方法,再就是拿到父类的原型对象
Child4.prototype.constrctor = Child4 //等于父子的原型constrctor都指向child4
因为引用的是同一个对象


 

缺点:子类创建的实例 是父类的实例 new child4().constrctor === Parent4

5.优化2

function Parent5() {
this.name = "Parent5"
this.play = [1, 2, 3]
}

function Child5() {
Parent5.call(this)
this.type = "Child5"
}
Child5.prototype = Object.create(Parent5.prototype) //隔离,
防止引用的是同一个对象 Child5.prototype.constrctor
= Child5

上面就是组合继承的完美写法

posted @ 2019-12-04 13:13  容忍君  阅读(256)  评论(0)    收藏  举报