单一职责原则
修改一个类的理由不应该超过一个,最小化对一个类需要修改的次数是非常必要。
一个类的功能不应该太复杂,如果过于复杂应该拆分成多个类
// ❌
class UserSettings {
constructor(user) {
this.user = user;
}
changeSettings(settings) {
if (this.verifyCredentials) {
// ...
}
}
verifyCredentials(user) {
// ...
}
}
// ✔️ 拆分为多个类,做到更大意义上的解耦
class UserAuth {
constructor(user) {
this.user = user;
}
verifyCredentials() {
// ...
}
}
class UserSettings {
constructor(user) {
this.user = user;
this.auth = new UserAuth(user);
}
changeSettings(settings) {
if (this.auth.verifyCredentials) {
// ...
}
}
}
开/闭原则
- 开
- 允许用户方便地扩展代码模块功能
- 闭
接口隔离原则
客户端不应该依赖不需要的接口,一个类对别一个类的依赖应该在建立在最小的接口上。
在JS中,当一个类需要许多参数才能生成一个对象时,或大多数时候不需要设置这么多参数,此时减少对配置参数数量的需要是有意义的
// ❌
/*
定义一个DOM遍历类
构造函数中传入一个settings对象,并调用setup来初始化rootNode和animationModule
所以实例化这个类时就需要转入rootNode和animationModule
*/
class DOMTraverser {
constructor(settings) {
this.settings = settings;
this.setup();
}
setup(settings) {
this.rootNode = this.settings.rootNode;
this.animationModule.setup();
}
traverse() {
// ...
}
}
let $ = new DOMTraverser({
rootNode: document.getElementsByTagName('body'),
animationModule: function() {
// ...
}
});
// ✔️ 但经发现animationModule这个模块不是每次遍历都都需要,所以改为给一个options选项,
/*
但经发现animationModule这个模块不是每次遍历都都需要。
所以改为给一个options选项,将不需要用到的属性放到options里
通过判断是否传入这个属性来进行相应的初始化
*/
class DOMTraverser {
constructor(settings) {
this.settings = settings;
this.options = settings.options;
this.setup();
}
setup(settings) {
this.rootNode = this.settings.rootNode;
this.setupOptions();
}
setupOptions() {
if (this.options.animationModule) {
// ...
}
}
traverse() {
// ...
}
}
let $ = new DOMTraverser({
rootNode: document.getElementsByTagName('body'),
options: {
animationModule: function() {}
}
});
继承使用Class而不是Function
ES5的方式在继承构造和方法定义方面可读性较差,在需要继承时优先选用ES6 class。
虽然本质是一样的,但对于读写的人来说这种方式最为简单。
语雀内容