javascript的原则

背景

这篇算是javascript的原则第二篇把,前一篇主要基础的讲解,这篇主要会讲一些数据结构和异常处理的讲解。

对象和数据结构

JavaScript 没有接口或类型, 所以坚持这个模式是非常困难的, 因为我们没有 public 和 private 关键字。 正因为如此, 使用 getters 和 setters 来访问对象上的数据比简单的在一个对象上查找属性 要好得多。 “为什么?” 你可能会问, 好吧, 原因请看下面的列表:

  • 当你想在获取一个对象属性的背后做更多的事情时, 你不需要在代码库中查找和修改每一处访问;
    使用 set 可以让添加验证变得容易;
    封装内部实现;
    使用 getting 和 setting 时, 容易添加日志和错误处理;
    继承这个类, 你可以重写默认功能;
    你可以延迟加载对象的属性, 比如说从服务器获取。
  • 使用 set 可以让添加验证变得容易;
  • 封装内部实现
  • 使用 getting 和 setting 时, 容易添加日志和错误处理;
  • 继承这个类, 你可以重写默认功能;
  • 你可以延迟加载对象的属性, 比如说从服务器获取。
Bad:class BankAccount {
  constructor() {
    this.balance = 1000;
  }
}
const bankAccount = new BankAccount();
// Buy shoes...
bankAccount.balance -= 100;

Goods:
>class BankAccount {
  constructor(balance = 1000) {
    this._balance = balance;
  }
  // It doesn't have to be prefixed with `get` or `set` to be a getter/setter
  set balance(amount) {
    if (verifyIfAmountCanBeSetted(amount)) {
      this._balance = amount;
    }
  }
  get balance() {
    return this._balance;
  }
verifyIfAmountCanBeSetted(val) {
    // ...
  }
}
const bankAccount = new BankAccount();
// Buy shoes...
bankAccount.balance -= shoesPrice;
// Get balance
let balance = bankAccount.balance;

私有变量

Bad:
>const Employee = function(name) {
  this.name = name;
};
Employee.prototype.getName = function getName() {
  return this.name;
};
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined

Good:
>const Employee = function (name) {
  this.getName = function getName() {
    return name;
  };
};
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe

ES2015/ES6 类优先与 ES5

Bad:
> const Animal = function(age) {
  if (!(this instanceof Animal)) {
    throw new Error('Instantiate Animal with `new`');
  }
  this.age = age;
};
Animal.prototype.move = function move() {};
const 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 liveBirth() {};
const 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 speak() {};

Good:
>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() { /* ... */ }
}

Class 支持方法链

Bad:
>class Car {
  constructor() {
    this.make = 'Honda';
    this.model = 'Accord';
    this.color = 'white';
  }
  setMake(make) {
    this.make = make;
  }
  setModel(model) {
    this.model = model;
  }
  setColor(color) {
    this.color = color;
  }
  save() {
    console.log(this.make, this.model, this.color);
  }
}
const car = new Car();
car.setColor('pink');
car.setMake('Ford');
car.setModel('F-150');
car.save();

Good:
>class Car {
  constructor() {
    this.make = 'Honda';
    this.model = 'Accord';
    this.color = 'white';
  }
  setMake(make) {
    this.make = make;
    // NOTE: Returning this for chaining
    return this;
  }
  setModel(model) {
    this.model = model;
    // NOTE: Returning this for chaining
    return this;
  }
  setColor(color) {
    this.color = color;
    // NOTE: Returning this for chaining
    return this;
  }
  save() {
    console.log(this.make, this.model, this.color);
    // NOTE: Returning this for chaining
    return this;
  }
}
const car = new Car()
  .setColor('pink')
  .setMake('Ford')
  .setModel('F-150')
  .save();

单一职责原则 (SRP)

正如代码整洁之道所述, “永远不要有超过一个理由来修改一个类”。

Bad:
>class UserSettings {
  constructor(user) {
    this.user = user;
  }
  changeSettings(settings) {
    if (this.verifyCredentials()) {
      // ...
    }
  }
  verifyCredentials() { }
}

Good:
>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()) {
      // ...
    }
  }
}

并发

使用 Promises, 不要使用回调

Bad:
>require('request').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin', (requestErr, response) => {
  if (requestErr) {
    console.error(requestErr);
  } else {
    require('fs').writeFile('article.html', response.body, (writeErr) => {
      if (writeErr) {
        console.error(writeErr);
      } else {
        console.log('File written');
      }
    });
  }
});

Good:
>require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then((response) => {
    return require('fs-promise').writeFile('article.html', response);
  })
  .then(() => {
    console.log('File written');
  })
  .catch((err) => {
    console.error(err);
  });

Async/Await 比 Promises 更加简洁

Promises 是回调的一个非常简洁的替代品, 但是 ES2017/ES8 带来的 async 和 await 提供了一个 更加简洁的解决方案。 你需要的只是一个前缀为 async 关键字的函数, 接下来就可以不需要 then 函数链来编写逻辑了。

Bad:
>require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then((response) => {
    return require('fs-promise').writeFile('article.html', response);
  })
  .then(() => {
    console.log('File written');
  })
  .catch((err) => {
    console.error(err);
  });

Good:
>async function getCleanCodeArticle() {
  try {
    const response = await require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
    await require('fs-promise').writeFile('article.html', response);
    console.log('File written');
  } catch(err) {
    console.error(err);
  }
}

格式化

使用一致的大小写
JavaScript 是无类型的, 所以大小写告诉你关于你的变量、 函数等的很多事情。 这些规则是主观的, 所以你的团队可以选择他们想要的。 重点是, 不管你们选择了什么, 要保持一致。

Bad:
>const DAYS_IN_WEEK = 7;
const daysInMonth = 30;
const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude'];
const Artists = ['ACDC', 'Led Zeppelin', 'The Beatles'];
function eraseDatabase() {}
function restore_database() {}
class animal {}
class Alpaca {}

Good:
>const DAYS_IN_WEEK = 7;
const DAYS_IN_MONTH = 30;
const songs = ['Back In Black', 'Stairway to Heaven', 'Hey Jude'];
const artists = ['ACDC', 'Led Zeppelin', 'The Beatles'];
function eraseDatabase() {}
function restoreDatabase() {}
class Animal {}
class Alpaca {}

注释

代码能够说清的尽量不要写注释

Bad:
>function hashIt(data) {
  // The hash
  let hash = 0;
  // Length of string
  const length = data.length;
  // Loop through every character in data
  for (let i = 0; i < length; i++) {
    // Get character code.
    const char = data.charCodeAt(i);
    // Make the hash
    hash = ((hash << 5) - hash) + char;
    // Convert to 32-bit integer
    hash &= hash;
  }
}

Good:
>function hashIt(data) {
  let hash = 0;
  const length = data.length;
  for (let i = 0; i < length; i++) {
    const char = data.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    // Convert to 32-bit integer
    hash &= hash;
  }
}

不要有日志式的评论

要用版本控制来查看评论

Bad:
>/**  2016-12-20: Removed monads, didn't understand them (RM)
  2016-10-01: Improved using special monads (JP)
  2016-02-03: Removed type-checking (LI)
  2015-03-14: Added combine with type-checking (JR)
 */
function combine(a, b) {
  return a + b;
}

Good:
>function combine(a, b) {
  return a + b;
}

千里之行,始于足下。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 写在开头 最近在看原则一本书,发现生活中和工作中很多都是有规律有原则的,代码的世界里也一样,代码其实是写给人看的,...
    i5yue阅读 819评论 0 0
  • (a fork of Airbnb's Javascript Style Guide) Strikingly ES...
    飘零_zyw阅读 1,612评论 1 2
  • 用更合理的方式写 JavaScript 目录 声明变量 对象 数组 字符串 函数 箭头函数 模块 迭代器和生成器 ...
    小红依阅读 2,212评论 0 5
  • 姓名:3D打印创客教育名片张艺楠 样子:四叶草形状 颜色:漂亮的淡蓝色(只有一台哦) 轻重:非常非常的轻 底板厚度...
    时光的漏斗wp阅读 419评论 0 1
  • 感谢阿里云9.9服务器学生计划,让我有机会实现自己小时候的梦想。为了能够写出这篇教程,我就默默把服务器(Ubunt...
    xuzhougeng阅读 2,814评论 0 7

友情链接更多精彩内容