js中OOP小指南

js中OOP小指南

在指南中,我将尝试解析以面向对象规范聚焦的es6的新特性。javascript

首先,java

什么是设计模式

范例是某个事务的例子或模型,在某种状况下,按照一种模式建立了计算机程序。es6

什么是面向对象

显然你意识到这是一种设计模式,像已经存在的这个模式,咱们还有许多其它的设计模式,好比函数式编程和反应式编程。编程

这种模式的特色

咱们在这个模式中所作的是以更接近实际的方式编程,咱们使用类,对象,方法,属性等进行编程,而且集成了抽象,封装,模块化,隐私,多态和继承等术语。设计模式

javascript的问题是,它不是一个很规范的语言,为何?由于javascript全部的都是对象,所以咱们可使用很著名的prototype来解决这个问题。模块化

在ES5中,咱们使用下面的例子实现工程模式:函数式编程

console.log('*** PERSON ***');
function Person (name) {
 this.name = name;
}
// 明确属性和方法
Person.prototype = {
   eyes: 2,
   mouth: 1,
   sleep: function () {
    return 'zzz';
   }
};
// 建立一个叫Nick的人
const p1 = new Person('Nick');

console.log(
  `name: ${p1.name}`,
  `eyes: ${p1.eyes}`,
  `mouth: ${p1.mouth}`,
   p1.sleep()
);
console.log('*** EMPLOYEE ***')
// 若是咱们有class属性,咱们能够继承person的属性
function Employee (name, salary) {
  this.name = name;
  this.salary = salary;
}
// Prototype 继承
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee; // Set his own constructor
// 如今能够作相同的事情了
// 建立一个employee
const em1 = new Employee('John', 3000);

console.log(
  `name: ${em1.name}`,
  `salary: ${em1.salary} USD`,
  `eyes: ${em1.eyes}`,
  `mouth: ${em1.mouth}`,
   em1.sleep()
);

如今使用ES6,用一种简单的方式实现上面的操做,可是必定记住这仅仅是语法糖:函数

class Person {
  constructor (name) {
    this.name = name;
    this.eyes = 2;
    this.mouth = 1;
  }
  sleep () {
    return 'zzz';
  }
}
class Employee extends Person {
  constructor (name, salary) {
    super(name);
    this.salary = salary;
  }
}
const p1 = new Person('Nick');
console.log(
  `name: ${p1.name}`,
  `eyes: ${p1.eyes}`,
  `mouth: ${p1.mouth}`,
   p1.sleep()
);
const em1 = new Employee('John', 3000);
console.log(
  `name: ${em1.name}`,
  `salary: ${em1.salary} USD`,
  `eyes: ${em1.eyes}`,
  `mouth: ${em1.mouth}`,
   em1.sleep()
);

在这种状况下,经过extends关键字咱们只需说:好吧,我想要继承Person类的属性。但在背后,这与咱们在使用es5示例中的原型所作的相同。oop

静态方法

class Dog {
  static whatIs() {
   return 'A dog is a beatiful animal';
  }
}
// 所以,咱们经过静态方法,不用实例化一个新的对象就能够访问方法
console.log( Dog.whatIs() );

私有属性

javascript并不像java和C#那样拥有私有属性。重要的是,在JavaScript中咱们有一个用于“私有”值的约定,该约定是在该单词以前使用下划线this

class Person {
 constructor (name, phone) { 
   this.name = name;
   this._phone = phone;
 }
}
const p1 = new Person('John', 544342212);
// 实际上 'phone' 不是一个私有属性,由于咱们能够这样使用:
console.log(p1._phone);

不过在ES6中,咱们有一个叫WeakMap的对象,它容许咱们建立私有属性。让咱们来看下:

// 由于它是保留字,因此不要使用private做为变量名称
const secret = new WeakMap();
class Person {
  constructor (name, phone) {
    this.name = name;
    secret.set(this, {_phonenumber: phone});
  }
}
const p1 = new Person('John', 544342212);
// 如今_phonenumber是一个私有属性
console.log(p1. _phonenumber); // Print's undefined

Getters 和 Setters

当咱们拥有私有方法时一般会建立一个返回私有值的公共方法,所以咱们必须返回一个值,并定义一个新的值。

const secret = new WeakMap();
class Person {
  constructor (name, phone) {
    this.name = name;
    secret.set(this, {_phonenumber: phone
  }
  get phoneNumber() {
    return secret.get(this)._phonenumber;
  }
  set phoneNumber(newNumber) {
    secret.get(this)._phonenumber = newNumber;
  }
}
const p1 = new Person('John', 544342212);
const p2 = new Person('Tom', 111111);
// 经过getter获取手机号
console.log(p1.phoneNumber); // Print's the number
// 设置新的手机号
p1.phoneNumber = 432232323;
p1.phoneNumber = 222222;
console.log(p1.phoneNumber, p2.phoneNumber); // 得到新的手机号

多态

在执行过程当中,一个对象引用它的类的事件或者任何子类的事件。子类可能会从新定义一种方法。

class Person {
  constructor(name) {
    this.name = name;
  }
  me() {
    return `My name is ${this.name}`;
  }
}
const axel = new Person('Axel');
console.log(axel.me());
  // ->  'My name is Axel'
class Employee extends Person {
  constructor (name, salary) {
    super(name);
    this.salary = salary;
  }
  me() {
    return `My name is ${this.name} and my salary is ${this.salary}`;
  } 
}
const nick = new Employee('Nick', 3000);
console.log(nick.me());
  // ->  'My name is Nick and my salary is 3000'

一些概念

  • class:建立新的类或者模型。
  • constructor: 实例化类时初始化对象的方法。
  • extends: 用于设置继承
  • super: 设置调用父亲的继承属性的方法。supe必须位于构造函数的第一行。
  • get: 获取某个值的方法。
  • set: 从新定义某个值的方法。
相关文章
相关标签/搜索