js中OOP小指南

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: 重新定义某个值的方法。

原文地址:https://www.cnblogs.com/open-wang/p/8970062.html

时间: 2024-10-09 07:31:00

js中OOP小指南的相关文章

学习JS中的小问题

1.如果载入的2个js文件中有重名函数,那么调用的时候怎么分别调? 第二个文件载入无效. 2.Query的checkbox对象的checked属性在选中时为checked,否则为undefined: JavaScript 的checkbox对象的checked属性在选中时为 true, 否则为 false. 3.本条内容摘自<JavaScript语言精粹>--电子工业出版社 定义函数的方式有两种:一种是函数声明,另一种是函数表达式. (1)函数声明: function funName(arg0

关于js中++的小问题

先看下面两个代码,为什么第一行正常(编译/运行),但第二行给出错误?注意是ReferenceError. [[]][0]++; []++; #Uncaught ReferenceError: Invalid left-hand side expression in postfix operation 第一想法[[]][0]应该和[ ]是一样的,所以两者都应该工作,或者两者都应该失败. 首先,这不是一个SyntaxError!这是一个运行时错误ReferenceError.所以[ ]++是语法允许

Js面向对象OOP学习指南

Type: 1.基本类型 each variable containing a primitive value uses its own storage space . tip: undefined == null true 2.引用类型

js中一些小技巧

//jquery控制div $("#p1").show();//显示 $("#p1").hide();//隐藏 //json值获取 var a={"a":"1","rows":[{"learn":"1"}]} var learn=a.rows[0].learn; //jquery控制样式 $("#a").attr("disabled&qu

JavaScript面向对象(一)——JS OOP基础与JS 中This指向详解

  前  言 JRedu 学过程序语言的都知道,我们的程序语言进化是从"面向机器".到"面向过程".再到"面向对象"一步步的发展而来.类似于汇编语言这样的面向机器的语言,随着时代的发展已经逐渐淘汰:而面向过程的语言也只有C语言老大哥依然坚挺:现在主流的语言(例如Java.C++.PHP等)都是面向对象的语言. 而我们的JavaScript语言,恰恰介于面向过程与面向对象之间,我们称它为"基于对象"的语言.但是,JS中的OOP依

js选择颜色小游戏(随机生成不含重复数字的数组,通过数组中的数控制定义好的数组)

<!DOCTYPE html><html> <head> <meta charset="utf-8"> <title>js网页版小游戏</title> <style media="screen"> .wrap { width: 577px; outline: 1px solid hotpink; margin: 100px auto; box-shadow: 0 0 5px; } .

js中的冒泡排序以及实现一个数组中得最到最大的数字小例

这其实是一个很简单的js就可以实现,当然一般情况就是利用for循环,从第一个跟第二个开始比较,根据大小交互位置,思路很简单. 也就是js中的冒泡排序 冒泡排序 时间复杂度为O(n^2),有两个优点: 1.“编程复杂度”很低,很容易写出代码: 2.具有稳定性,这里的稳定性是指原序列中相同元素的相对顺序仍然保持到排序后的序列,而堆排序.快速排序均不具有稳定性. 实现基本思路:冒泡排序是经过n-1趟子排序完成的,第i趟子排序从第1个数至第n-i个数,若第i个数比后一个数大(则升序,小则降序)则交换两数

微信小程序image组件binderror使用例子(对应html、js中的onerror)

官方文档  binderror HandleEvent 当错误发生时,发布到 AppService 的事件名,事件对象event.detail = {errMsg: 'something wrong'} 在微信小程序开发中,我们使用列表包含图片,如果这个图片链接404错误,那么我们应该给它提供一个默认的友好URL地址.html和js中使用onerror事件就可以了 <img src="image.gif" onerror="this.src='https:w.chesu

JS中关于把函数作为另一函数的参数的几点小总结

//JS中关于把函数作为函数的参数来传递的问题的小总结//第一,最简单的形式无参函数,直接形式函数的函数名放到括号中,再在执行部分这个函数即可.//当然调用时要穿另一个真正的定义好的函数/*function test1(Func){Func();}function test2(){alert("我是test2");}test1(test2);*/ //第二种,带参数的普通调用法.跟第一种唯一的区别就是在定义主函数的执行语句里调用参数函数时该把参数加上/*function test1(F