浅谈JavaScript 代码整洁之道(11)

前提已经提到,JavaScript 没有接口,因此抽象依赖于隐性契约。也就是说,一个对象/类会把方法和属性暴露给另一个对象/类。在下面的例子中,隐性契约是任何用于 InventoryTracker 的 Request 模块都应该拥有 requestItems 方法。

不好:

class InventoryTracker {
 constructor(items) {
  this.items = items;

  // 不好:我们创建了一个依赖于特定请求的实现。
  // 我们应该只依赖请求方法:`request` 的 requestItems
  this.requester = new InventoryRequester();
 }

 requestItems() {
  this.items.forEach((item) => {
   this.requester.requestItem(item);
  });
 }
}

class InventoryRequester {
 constructor() {
  this.REQ_METHODS = ['HTTP'];
 }

 requestItem(item) {
  // ...
 }
}

let inventoryTracker = new InventoryTracker(['apples', 'bananas']);
inventoryTracker.requestItems();

好:

class InventoryTracker {
 constructor(items, requester) {
  this.items = items;
  this.requester = requester;
 }

 requestItems() {
  this.items.forEach((item) => {
   this.requester.requestItem(item);
  });
 }
}

class InventoryRequesterV1 {
 constructor() {
  this.REQ_METHODS = ['HTTP'];
 }

 requestItem(item) {
  // ...
 }
}

class InventoryRequesterV2 {
 constructor() {
  this.REQ_METHODS = ['WS'];
 }

 requestItem(item) {
  // ...
 }
}

// 通过构建外部依赖并注入它们,我们很容易把请求模块替换成
// 一个使用 WebSocket 的新模块。
let inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterV2());
inventoryTracker.requestItems();

多用 ES6 类语法,少用 ES5 构造函数语法

在经典的 ES5 的类定义中,很难找到易读的继承、构造、方法定义等。如果你需要继承(你会发现做不到),那就应该使用类语法。不过,应该尽可能使用小函数而不是类,直到你需要更大更复杂的对象。

不好:

var Animal = function(age) {
  if (!(this instanceof Animal)) {
    throw new Error("Instantiate Animal with `new`");
  }

  this.age = age;
};

Animal.prototype.move = function() {};

var Mammal = function(age, furColor) {
  if (!(this instanceof Mammal)) {
    throw new Error("Instantiate Mammal with `new`");
  }

  Animal.call(this, age);
  this.furColor = furColor;
};

Mammal.prototype = Object.create(Animal.prototype);
Mammal.prototype.constructor = Mammal;
Mammal.prototype.liveBirth = function() {};

var Human = function(age, furColor, languageSpoken) {
  if (!(this instanceof Human)) {
    throw new Error("Instantiate Human with `new`");
  }

  Mammal.call(this, age, furColor);
  this.languageSpoken = languageSpoken;
};

Human.prototype = Object.create(Mammal.prototype);
Human.prototype.constructor = Human;
Human.prototype.speak = function() {};

好:

class Animal {
  constructor(age) {
    this.age = age;
  }

  move() {}
}

class Mammal extends Animal {
  constructor(age, furColor) {
    super(age);
    this.furColor = furColor;
  }

  liveBirth() {}
}

class Human extends Mammal {
  constructor(age, furColor, languageSpoken) {
    super(age, furColor);
    this.languageSpoken = languageSpoken;
  }

  speak() {}
}


      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/417.html