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// 现在可以做相同的事情了// 创建一个employeeconst 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小指南
原文地址:https://www.cnblogs.com/open-wang/p/8970062.html