js中OOP小指南
阿新 • • 發佈:2018-04-29
程序 屬性和方法 obj 操作 script hat setter 我想 當我
js中OOP小指南
在指南中,我將嘗試解析以面向對象規範聚焦的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示例中的原型所做的相同。
靜態方法
class Dog {
static whatIs() {
return ‘A dog is a beatiful animal‘;
}
}
// 因此,我們通過靜態方法,不用實例化一個新的對象就可以訪問方法
console.log( Dog.whatIs() );
私有屬性
javascript並不像java和C#那樣擁有私有屬性。重要的是,在JavaScript中我們有一個用於“私有”值的約定,該約定是在該單詞之前使用下劃線:
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: 重新定義某個值的方法。
js中OOP小指南