CD's blog CD's blog
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

CD_wOw

内卷的行情,到不了的梦
首页
  • HTMLCSS
  • JavaScript
  • Vue
  • TypeScript
  • React
  • Node
  • Webpack
  • Git
  • Nestjs
  • 小程序
  • 浏览器网络
  • 学习笔记

    • 《TypeScript 从零实现 axios》
    • Webpack笔记
  • JS/TS教程

    • 《现代JavaScript》教程
🔧工具方法
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 简介

  • JavaScript 基础知识

  • 数据类型

  • 函数进阶内容

  • 对象属性配置

  • 原型,继承

  • 类

    • Class 基本用法
    • 私有的和受保护的属性和方法
    • Mixin 模式
    • 类继承
    • 扩展内建类
      • 静态属性和静态方法
      • 类检查:"instanceof"
    • 错误处理

    • Promise,asyncawait

    • Generator,高级 iteration

    • 模块

    • 杂项

    • 《现代JavaScript》教程
    • 类
    CD_wOw
    2020-12-13
    目录

    扩展内建类

    内建的类,例如 Array,Map 等也都是可以扩展的(extendable)。

    例如,这里有一个继承自原生 Array 的类 PowerArray:

    // 给 PowerArray 新增了一个方法(可以增加更多)
    class PowerArray extends Array {
      isEmpty() {
        return this.length === 0;
      }
    }
    
    let arr = new PowerArray(1, 2, 5, 10, 50);
    alert(arr.isEmpty()); // false
    
    let filteredArr = arr.filter(item => item >= 10);
    alert(filteredArr); // 10, 50
    alert(filteredArr.isEmpty()); // false
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

    请注意一个非常有趣的事儿。内建的方法例如 filter,map 等 — 返回的正是子类 PowerArray 的新对象。它们内部使用了对象的 constructor 属性来实现这一功能。

    在上面的例子中,

    arr.constructor === PowerArray
    
    1

    当 arr.filter() 被调用时,它的内部使用的是 arr.constructor 来创建新的结果数组,而不是使用原生的 Array。这真的很酷,因为我们可以在结果数组上继续使用 PowerArray 的方法。

    甚至,我们可以定制这种行为。

    我们可以给这个类添加一个特殊的静态 getter Symbol.species。如果存在,则应返回 JavaScript 在内部用来在 map 和 filter 等方法中创建新实体的 constructor。

    如果我们希望像 map 或 filter 这样的内建方法返回常规数组,我们可以在 Symbol.species 中返回 Array,就像这样:

    class PowerArray extends Array {
      isEmpty() {
        return this.length === 0;
      }
    
      // 内建方法将使用这个作为 constructor
      static get [Symbol.species]() {
        return Array;
      }
    }
    
    let arr = new PowerArray(1, 2, 5, 10, 50);
    alert(arr.isEmpty()); // false
    
    // filter 使用 arr.constructor[Symbol.species] 作为 constructor 创建新数组
    let filteredArr = arr.filter(item => item >= 10);
    
    // filteredArr 不是 PowerArray,而是 Array
    alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    正如你所看到的,现在 .filter 返回 Array。所以扩展的功能不再传递。

    其他集合的工作方式类似

    其他集合,例如 Map 和 Set 的工作方式类似。它们也使用 Symbol.species。

    # 内建类没有静态方法继承

    内建对象有它们自己的静态方法,例如 Object.keys,Array.isArray 等。

    如我们所知道的,原生的类互相扩展。例如,Array 扩展自 Object。

    通常,当一个类扩展另一个类时,静态方法和非静态方法都会被继承。这已经在 静态属性和静态方法 (opens new window) 中详细地解释过了。

    但内建类却是一个例外。它们相互间不继承静态方法。

    例如,Array 和 Date 都继承自 Object,所以它们的实例都有来自 Object.prototype 的方法。但 Array.[[Prototype]] 并不指向 Object,所以它们没有例如 Array.keys()(或 Date.keys())这些静态方法。

    这里有一张 Date 和 Object 的结构关系图:

    正如你所看到的,Date 和 Object 之间没有连结。它们是独立的,只有 Date.prototype 继承自 Object.prototype,仅此而已。

    与我们所了解的通过 extends 获得的继承相比,这是内建对象之间继承的一个重要区别。

    编辑 (opens new window)
    #现代JavaScript
    上次更新: 2021/08/22, 01:09:59
    类继承
    静态属性和静态方法

    ← 类继承 静态属性和静态方法→

    最近更新
    01
    gsap动画库学习笔记 - 持续~
    06-05
    02
    远程组件加载方案笔记
    05-03
    03
    小程序使用笔记
    03-29
    更多文章>
    Theme by Vdoing | Copyright © 2020-2023 CD | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式