zoukankan      html  css  js  c++  java
  • 代码整洁之道——4、类

    一、优先使用ES6语法的类而不是ES5的纯函数

    传统的ES5类语法很难拥有类的继承、构造函数和方法的定义。如果你需要使用继承(要注意的是,你可能不需要),那么就用ES2015/ES6的类。但是,在你发现你需要更大更复杂的对象的之前,尽量使用小巧的函数。

    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:
    //定义一个动物类,有age属性和move方法
    class Animal {
      constructor(age) {
        this.age = age;
      }
      move() { /* ... */ }
    }
    //定义一个哺乳动物类继承动物类,除了animal的属性和方法外还有自己的liveBirth方法
    class Mammal extends Animal {
      constructor(age, furColor) {
        super(age);
        this.furColor = furColor;
      }
    
      liveBirth() { /* ... */ }
    }
    
    //定义人类这个类继承哺乳动物,除哺乳动物的属性和方法外,还有自己的languageSpoken属性和speak方法
    class Human extends Mammal {
      constructor(age, furColor, languageSpoken) {
        super(age, furColor);
        this.languageSpoken = languageSpoken;
      }
    
      speak() { /* ... */ }
    }

    二、使用方法链

    这个模式在JS中非常有用,你可以在很多像jquery、lodash等库中看到。它可以让你的代码简洁而富有表现力。正是因为这个原因,所以我说使用方法链,然后看下你的代码可以变得多么简洁。在你的类函数中,在每个函数的最后简单的返回this,你就可以把这个类的方法链在一起。

    Bad:
    class Car {
      constructor(make, model, color) {
        this.make = make;
        this.model = model;
        this.color = color;
      }
    
      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('Ford','F-150','red');
    car.setColor('pink');
    car.save();
    
    Good:
    class Car {
      constructor(make, model, color) {
        this.make = make;
        this.model = model;
        this.color = color;
      }
    
      setMake(make) {
        this.make = make;
        // 为链式调用返回this
        return this;
      }
    
      setModel(model) {
        this.model = model;
        // 为链式调用返回this
        return this;
      }
    
      setColor(color) {
        this.color = color;
        // 为链式调用返回this
        return this;
      }
    
      save() {
        console.log(this.make, this.model, this.color);
       // 为链式调用返回this
        return this;
      }
    }
    
    //链式调用
    const car = new Car('Ford','F-150','red')
      .setColor('pink')
      .save();

    三、优先使用组合而不是继承

    正如著名的设计模式(Design Patterns )所论述的一样,你应该尽可能的使用组合而不是继承。使用组合和继承的优点都有很多。这则论述的主要观点是:如果你本来想用继承,那么想想组合能不能替代,大部分情况下都是可以的。

    你可能会想,什么时候我需要使用继承呢?这取决于你手头的问题,这有个列表说明什么时候使用继承比使用组合好:

    1、你的继承代表的“是一个”的关系而不是“有一个”的关系。(人类继承自动物,用户有用户明细Human->Animal vs. User->UserDetails)

    2、你可以重用基类的代码。(人类像动物一样拥有move方法)

    3、你想要通过改变积累来全局(改变子类继承自基类的方法)(改变动物运动时的热量消耗)

    Bad:
    class Employee {
      constructor(name, email) {
        this.name = name;
        this.email = email;
      }
    
      // ...
    }
    
    //不好是因为EmployeeTaxData 并不是Employee 的一种类型。而是Employee 有EmployeeTaxData 。
    class EmployeeTaxData extends Employee {
      constructor(ssn, salary) {
        super();
        this.ssn = ssn;
        this.salary = salary;
      }
    
      // ...
    }
    
    
    Good:
    class EmployeeTaxData {
      constructor(ssn, salary) {
        this.ssn = ssn;
        this.salary = salary;
      }
    
      // ...
    }
    
    class Employee {
      constructor(name, email) {
        this.name = name;
        this.email = email;
      }
    //员工有税率数据
      setTaxData(ssn, salary) {
        this.taxData = new EmployeeTaxData(ssn, salary);
      }
      // ...
    }
  • 相关阅读:
    linux运维之分析系统负载及运行状况
    linux运维之分析日志相关命令(1)
    centos7修改网卡名称为eth0
    LANMP环境编译参数查看方法
    自动化部署之搭建yum仓
    浙大 PAT 乙级 1001-1075 目录索引
    更改docker服务网段分配地址
    MySQL主从复制(Replication for Backup)
    MySQL读写分离-简单思考
    NGINX负载均衡缓存配置
  • 原文地址:https://www.cnblogs.com/xxchi/p/7236677.html
Copyright © 2011-2022 走看看