你不知道的js—构造函数'类'

187 阅读4分钟

概念

很多程序员工作好几年,竟然不知道什么是面向对象编程

面向对象编程的核心就是类,面向类的设计模式:实例化(instantiation)、继承(inheritance)和(相对)多态(polymorphism)。这些名词我们会全都解释清楚。

类理论

面向对象编程强调的是数据和操作数据的行为本质上是互相关联的(当然,不同的数据有不同的行为),因此好的设计就是把数据以及和它相关的行为打包(或者说封装)起来

例子:把“交通工具”当作一个广泛的类Vehicle,飞机、火车和汽车都可当作一个类。Vehicle的定义可能包含推进器(比如引擎)、载10人的能力等,飞机、火车和汽车在拥有Vehicle的能力的同时,又都拥有自己的独特能力:飞机在天上、火车在轨道上、汽车在公路上。又可以生产出很多的飞机、火车和汽车。

  • 类:Vehicle是父类,飞机、火车和汽车都是子类
  • 继承:Vehicle拥有的能力,飞机、火车和汽车都有;
  • 多态:Vehicle默认能载10人,飞机载80人、火车载1000人、汽车载4人,每个子类从父类继承来的能力得到了改变;
  • 实例化:飞机、火车和汽车功能固定后,可以生产出大量独立的飞机、火车和汽车;

重点:当飞机、火车和汽车功能固定后,就形成了模型。可以根据模型量产出无限个相同的产品,不需要每次生产时再确定它的功能。这种操作简直太棒了。

这种基于固定模块实现量产的方式就是:面向对象编程;

“类”设计模式

你可能听过‘设计模式’这个词,比如迭代器模式、观察者模式、工厂模式、单例模式等等。它们都是在(低级)面向对象类的基础上实现了所有(高级)设计模式,似乎面向对象是优秀代码的基础。

JavaScript中的“类”

JavaScript中实际上有类呢?简单来说:不是。

类是一种设计模式,js其实是通过原型链模拟,实现类的功能。为了满足对于类设计模式的最普遍需求,JavaScript提供了一些近似类的语法。

代码实现例子

为方便实现,使用ES6的class写法。

定义父类Vehicle

Vehicle有引擎、载10人的能力;

class Vehicle{
    engine() {
        return '我是引擎';
    }
    load() {
        return '我能载10人';
    }
}

飞机、火车和汽车继承Vehicle

飞机、火车和汽车都继承了engine功能,又都同时扩展了自己的way功能。

class Car extends Vehicle {
    way() {
        return '我在公路上';
    }
}
class Plane extends Vehicle {
    way() {
        return '我在天上';
    }
}
class Train extends Vehicle {
    way() {
        return '我在轨道上';
    }
}
const car = new Car();
console.log(car.engine()) // 我是引擎
console.log(car.way())  // 我在公路上
const plane = new Plane();
console.log(plane.engine())  // 我是引擎
console.log(plane.way())  // 我在天上
const train = new Train();
console.log(train.engine())  // 我是引擎
console.log(train.way()) // 我在轨道上

多态

每个子类都重新定义了load功能。如果没有定义,就会继续使用父类的load。

class Car extends Vehicle {
    load() {
        return '我能载4人';
    }
    way() {
        return '我在公路上';
    }
}
class Plane extends Vehicle {
    load() {
        return '我能载80人';
    }
    way() {
        return '我在天上';
    }
}
class Train extends Vehicle {
    load() {
        return '我能载1000人';
    }
    way() {
        return '我在轨道上';
    }
}
const car = new Car();
console.log(car.load()) // 我能载4人
const plane = new Plane();
console.log(plane.load())  // 我能载80人
const train = new Train();
console.log(train.load())  // 我能载1000人

实例化

使用Car举例,此时拥有Car的模型,我们可以量产了。

  1. 需要传参数时,要用constructor接收,如果是子类需要执行super,super的参数会传进父类的constructor函数。
  2. 看结果,多个car相互独立。既有相同的engine、way,还有自己独特的名字。
class Car extends Vehicle {
    constructor(name) {
        super();
        this.name = name;
    }
    load() {
        return '我能载4人';
    }
    way() {
        return '我在公路上';
    }
}
const car1 = new Car('保时捷');
console.log(car1.name) // 保时捷
console.log(car1.engine())  // 我是引擎
console.log(car1.way())   // 我在公路上
const car2 = new Car('长城');  
console.log(car2.name)   // 长城
console.log(car2.engine())   // 我是引擎
console.log(car2.way())   // 我在公路上
const car3 = new Car('奔驰');
console.log(car3.name)   // 奔驰
console.log(car3.engine())   // 我是引擎
console.log(car3.way())   // 我在公路上

继承和实例化

必须理解原型才能明白继承和实例化。讲完原型后,再写两篇文章讲解吧。本文懂得怎么用就可以了。