JavaScript 与 OOP
Posted GoldenaArcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 与 OOP相关的知识,希望对你有一定的参考价值。
javascript 与 OOP
面向对象编程(Objected- Oriented Programming,OOP)是一种以对象和类为基础进行开发的编程思想,主要核心组成部分有四个:
-
属性(attributes)
可以代表其状态(state)的变量(variables)
-
函数(methods)
可以代表其行为(behavior),函数可以直接操纵类的属性,可以接受参数,返回值,用于实现对类的操作
-
类(classes)
包含状态(states)与行为(behaviors)
-
对象(objects)
对象的定义为 创建类的蓝图
OOP 的四大原则包涵:
- 封装 Encapsulation
- 抽象 Abstract
- 继承 Inheritance
- 多态 Polymorphism
封装 Encapsulation
封装的主要用途在于不暴露数据的操作与数据本身,以 Movie 这个类为例,它可以包含 3 个属性:电影名(title)、年(year)与类别(genre)。
JavaScript
class Movie
#title = '';
#year = -1;
#genre = '';
// constructor
constructor(t = '', y = -1, g = '')
this.title = t;
this.year = y;
this.genre = g;
set title(t)
this.#title = t;
get title()
return this.#title;
set year(y)
this.#year = y;
get year()
return this.#year;
set genre(g)
this.#genre = g;
get genre()
return this.#genre;
printDetails()
console.log('Title: ', this.title);
console.log('Year: ', this.year);
console.log('Genre: ', this.genre);
const movie = new Movie('The Lion King', 1994, 'Adventure');
movie.printDetails();
console.log('---');
movie.title = 'Forrest Gump';
console.log('New title: ', movie.title);
运行结果:
这是一个至少 ES6 以后的写法,其中 #attributes
的写法代表了私有变量,这也意味着实例化的对象无法直接访问该变量,如:
而可以直接获取 movie.genre
则是依赖于 setter/getter 的实现,如果类中没有 getter 的实现,那么输出就会直接变成 undefined:
修改私有属性值也依赖于 setter:
可以说 private properties 让 JS 的 OOP 实现更贴合其他语言的实现,也更有意义了——不然都是 public,就算会约定俗成的使用 _properties
代表私有属性,也可能会引起滥用。
TypeScript
class Movie
private _title: string;
constructor(title = '', private year = -1, private genre = '')
this.title = title;
public get title()
return this._title;
public set title(t: string)
this._title = t;
printDetails()
console.log('Title: ', this.title);
console.log('Year: ', this.year);
console.log('Genre: ', this.genre);
const movie = new Movie('The Lion King', 1994, 'Adventure');
movie.printDetails();
console.log('---');
movie.title = 'Forrest Gump';
console.log('New title: ', movie.title);
TS 的变量名其实会稍微有点麻烦,如果用构造函数的缩写,那么 getter/setter 就会有重复变量的问题:
封装的另一个好处就在于属性的获取方式会变得更简单一些,比如说获取一些需要转换的值,可以直接在 setter/getter 中进行计算:
继承 Inheritance
先把继承提出来是因为抽象要用。
继承主要有的一个 IS-A 的关系,即子类是复类的一种,如车是一种载具,鸟是一种动物等。
继承的方式主要有以下几种:
-
单独继承 Single Inheritance
即 燃油车 继承载具。
-
多继承 Multiple inheritance
这里混合汽车继承了油车,也继承了电车。
目前我接触到的语言……好像只有 C++ 支持多继承。
-
多重继承 Multi-level inheritance
这里 汽油车 继承 燃油车。
-
层次继承 Hierarchical inheritance
这里油车电车都继承了载具。
-
混合继承 Hybrid inheritance
混合继承是多继承+多层继承的组合
JavaScript
// Base class (Parent)
class Vehicle
constructor(name, model)
this.name = name;
this.model = model;
getName()
return 'The car is a ' + this.name + ' ' + this.model;
// Single inheritance
// FuelCar class extending from Vehicle class
// Derived class (Child)
class FuelCar extends Vehicle
constructor(name, model, combustType)
super(name, model);
this.combustType = combustType;
getFuelCar()
return this.getName() + ', combust type is ' + this.combustType;
// Hierarchical inheritance
// Alongside the FuelCar class, the ElectricCar class is also extending from Vehicle class
// Another Derived class (Child)
class ElectricCar extends Vehicle
constructor(name, model, batteryPower)
super(name, model);
this.batteryPower = batteryPower;
getElectricCar()
return this.getName() + ', battery power is ' + this.batteryPower;
// Multi-level inheritance
// GasolineCar class is derived from the FuelCar class, which is further derived from the Vehicle class
// Derived class (Grandchild)
class GasolineCar extends FuelCar
constructor(name, model, combustType, gasCapacity)
super(name, model, combustType);
this.gasCapacity = gasCapacity;
getGasolineCar()
return this.getFuelCar() + ', gas capacity is ' + this.gasCapacity;
// JavaScript does not support Multiple inheritance via classes
// main
console.log('Single inheritance:');
let Fuel = new FuelCar('Tesla', 'ModelX', '200MWH');
console.log(Fuel.getFuelCar());
console.log(' ');
console.log('Hierarchical inheritance:');
let Electric = new ElectricCar('Honda', 'Accord', 'Petrol');
console.log(Electric.getElectricCar());
console.log(' ');
console.log('Multi-Level inheritance:');
let Gasoline = new GasolineCar('Toyota', 'Corolla', 'Gasoline', '300MWH');
console.log(Gasoline.getGasolineCar());
console.log(' ');
console.log('JavaScript does not support Multiple inheritance via classes');
TypeScript
TS 的实现和 TS 没什么区别,不过这里因为用了缩写,所以代码量可以稍微少一点点。
// Base class (Parent)
class Vehicle
constructor(private name: string, private model: string)
getName()
return 'The car is a ' + this.name + '以上是关于JavaScript 与 OOP的主要内容,如果未能解决你的问题,请参考以下文章