个人技术站点JASONWU

Keep Coding


  • 主页

  • 文章

  • 搜索

JavaScrip OOP:ES6 Class

新建: 2021-06-01 编辑: 2021-06-18   |   分类: JavaScript   | 字数: 1456 字

ES6 Class 特点

  • 仅仅是构造函数的语法糖
  • 不会 Hoisted
  • First Class Citizen,即类可以被当成参数使用
  • Class Body 永远都只在 Strict Mode('use strict';)下执行

类表达式 vs 类声明

与函数一样,类的定义也有两种方式:

  • 类表达式(Class Expression)
  • 类声明(Class Declaration)

但与函数不同的是:类声明不会 Hoisted!

JavaScript
1// 类声明
2class User {
3}
4
5// 类表达式
6const Guest = class {};

语法糖

JavaScript
 1class User {
 2  constructor(name, age) {
 3    this.name = name;
 4    this.age = age;
 5  }
 6
 7  // 方法是被加入到 `.prototype` 原型对象中
 8  sayHi() {
 9    console.log(`你好,${this.name}`);
10  }
11}
12
13// 证明 ES6 Class 仅仅是构造函数的语法糖
14User.prototype.showAge = function () {
15  console.log(`年龄:${this.age}`);
16};
17
18const jason = new User('Jason', 25);
19jason.sayHi(); // 你好,Jason
20jason.showAge(); // 年龄:25
21
22// 检查原型链
23console.dir(jason);

Getter 和 Setter

约定俗成:当 Getter/Setter 中的属性名与字段同名时,加上 _ 前缀作为区分。

JavaScript
 1class User {
 2  constructor(name, age) {
 3    // 这里定义的变量叫字段(field)
 4    this.name = name;
 5    this.age = age;
 6  }
 7
 8  // 这里定义的变量叫属性(property)
 9  set age(age) {
10    if (age >= 0 && age <= 100) {
11      // 当属性和字段同名时,加上 `_` 前缀,并定义相应 Getter 方法
12      this._age = age;
13    } else {
14      throw new Error(`${age}不在0~100的年龄范围内`)
15    }
16  }
17
18  get age() {
19    return this._age;
20  }
21}
22
23const jason = new User('Jason', 25);
24console.log(jason.age); // 25
25
26jason.age = 99;
27console.log(jason.age); // 99

静态属性和方法

JavaScript
 1class User {
 2  constructor(name, age) {
 3    this.name = name;
 4    this.age = age;
 5  }
 6
 7  // 方式一(推荐)
 8  static versionPrefix = 'v';
 9
10  static info () {
11    console.log(`版本:${User.versionPrefix}${User.versionNum}`);
12  }
13}
14
15// 方式二
16User.versionNum = '1.0.0';
17
18const jason = new User('Jason', 25);
19
20console.log(jason.versionNum); // undefined
21
22console.log(`${User.versionPrefix}${User.versionNum}`); // v1.0.0
23User.info(); // 版本:v1.0.0

继承与多态

JavaScript
 1class User {
 2  constructor(name, age) {
 3    this.name = name;
 4    this.age = age;
 5  };
 6
 7  sayHi() {
 8    console.log(`你好,${this.name}`);
 9  }
10}
11
12class Vip extends User {
13  constructor(name, age, level) {
14    // 必须位于构造方法的第一句
15    super(name, age);
16
17    this.level = level;
18  };
19
20  sayHi() {
21    console.log(`用户:${this.name},VIP 等级:${this.level}`);
22  }
23}
24
25const jason = new Vip('Jason', 25, '3');
26
27jason.sayHi(); // 用户:Jason,VIP 等级:3
28
29// 检查原型链
30console.log(jason instanceof Vip); // true
31console.log(jason instanceof User); // true
32console.log(jason instanceof Object); // true

封装

伪私有属性和方法

因很长一段时间 JS 都是没有私有特性,故约定俗成:以 _ 开头的属性或方法就是私有的,其他开发人员不应直接操作这类名称的变量。

JavaScript
 1class User {
 2  constructor(name, passwd) {
 3    // 受保护的属性
 4    this._rpasswd = '123';
 5
 6    this.name = name;
 7    this.passwd = passwd;
 8  };
 9
10  login() {
11    if (this._check()) return console.log(`${this.name},登录成功`);
12
13    console.log('用户名或密码错误');
14  }
15
16  // 受保护的方法
17  _check() {
18    return this.passwd === this._rpasswd;
19  }
20}
21
22const jason = new User('Jason', '123');
23jason.login(); // Jason,登录成功
24
25// 因为不是语言特性,所以仍可访问,但此时开发者自身是知道执行了不合规的操作
26console.log(jason._rpasswd); // 123
27console.log(jason._check()); // true

真私有字段和方法

Class field declarations for JavaScript 中为 JS 引入了私有字段和方法(同样适用于静态)。

JavaScript
 1class User {
 2  // 1) Public fields
 3  name;
 4  passwd;
 5
 6  // 2) Private field
 7  #rPasswd = '123';
 8
 9  constructor(name, passwd) {
10    this.name = name;
11    this.passwd = passwd;
12  };
13
14  // 3) Public method
15  login() {
16    if (this.#check()) return console.log(`${this.name},登录成功`);
17
18    console.log('用户名或密码错误');
19  }
20
21  // 4) private method
22  #check() {
23    return this.passwd === this.#rPasswd;
24  }
25}
26
27const jason = new User('Jason', '123');
28jason.login(); // Jason,登录成功
29
30// 因为是语言特性,所以真正实现了私有
31// console.log(jason.#rPasswd); // Uncaught SyntaxError
32// console.log(jason.#check()); // Uncaught SyntaxError

链式调用

JavaScript
 1class Account {
 2  constructor() {
 3    this._movements = [];
 4  }
 5
 6  deposit(val) {
 7    this.movements.push(val);
 8    return this; // 返回对象本身
 9  }
10
11  withdraw(val) {
12    this.deposit(-val);
13    return this; // 返回对象本身
14  }
15
16  get movements() {
17    return this._movements;
18  }
19}
20
21const account = new Account();
22
23account
24  .deposit(100)
25  .withdraw(50)
26  .withdraw(20)
27  .deposit(70);
28
29console.log(account.movements); // [100, -50, -20, 70]
#oop#

文章:JavaScrip OOP:ES6 Class

链接:https://www.wuxianjie.net/posts/js-oop-class/

作者:吴仙杰

文章: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处!

Sass 7-1 Pattern
JavaScript OOP:原型链
  • 文章目录
  • 站点概览
吴仙杰

吴仙杰

🔍 Ctrl+K / ⌘K

27 文章
9 分类
25 标签
邮箱 GitHub
  • ES6 Class 特点
  • 类表达式 vs 类声明
  • 语法糖
  • Getter 和 Setter
  • 静态属性和方法
  • 继承与多态
  • 封装
    • 伪私有属性和方法
    • 真私有字段和方法
  • 链式调用
© 2021-2025 吴仙杰 保留所有权利 All Rights Reserved
浙公网安备 33010302003726号 浙ICP备2021017187号-1
0%