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: 從新定義某個值的方法。
相關文章
相關標籤/搜索