JavaScript---面向对象

116 阅读1分钟

类的声明

1. 通过构造函数声明

function Animal() {
    // this表明这是一个构造函数
    this.name = name;
}

2. es6声明

class Animal2 {
    constructor() {
        this.name = name;
    }
}

将类实例化成对象:通过new就可以实例化一个类

console.log(new Animal, new Animal2)

类的继承(本质就是原型链)

1. 通过构造函数实现继承

function Parent1() {
    this.name = 'parent1'
}
Parent1.prototype.say = function () {
    console.log('parent1 原型链')
}
function Child1() {
    // call\apply   改变函数运行的上下文
    // 将父级构造函数的this指向子构造函数的实例上去
    // 导致父级的构造函数里的内容子类里面也有
    Parent1.call(this)
    this.type = 'child1'
}
console.log(new Child1)

缺点:父类原型链上面的东西并没有被子类所继承

2. 借助原型链实现继承

function Parent2() {
    this.name = 'parent2'
    this.play = [1, 2, 3];
}

function Child2() {
    this.type = 'child2'
}
        
// prototype属性是为了让这个构造函数的实例能访问到他的原型对象上
Child2.prototype = new Parent2();

// Parent2.prototype.say = function(){
//     console.log('parent2 原型链')
// }

console.log(new Child2().__proto__)

let s1 = new Child2()
let s2 = new Child2()
console.log(s1.play, s2.play)
s1.play.push(4)

缺点:原型链中的原型对象是共用的
所以改其中一个原型对象的时候其实就是改另一个的原型对象

3. 组合方式

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

function Child3() {
    Parent3.call(this)
    this.type = 'child3'
}

Child3.prototype = new Parent3();

Parent3.prototype.say = function () {
    console.log('parent3 原型链')
}

let s3 = new Child3()
let s4 = new Child3()
s3.play.push(4)
console.log(s3.play, s4.play)

缺点:父级构造函数执行了两次(没有必要)

4. 组合优化方式1

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

function Child4() {
    Parent4.call(this)
    this.type = 'child4'
}

Child4.prototype = Parent4.prototype;

let s5 = new Child4()
let s6 = new Child4()
s5.play.push(4)
console.log(s5.play, s6.play)

console.log(s5 instanceof Child4, s5 instanceof Parent4)

// 如何判断一个是直接由他的子类实例化的还是他的父类实例化的
console.log(s5.constructor)

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)  // __proto__
Chil5.prototype.constructor = Chil5;

let s7 = new Child5()

console.log(s7 instanceof Chil5, s7 instanceof Parent5)

// 如何判断一个是直接由他的子类实例化的还是他的父类实例化的
console.log(s7.constructor)