每日读《你不知道的JavaScript(上)》| 类

引言

上一篇文章我们介绍完了对象的知识,了解了对象的行为和特性,所以这里我们就来到了"类"的技能点。

借此机会也夯实一下面向对象的基础吧~

类的基础概念

什么是类?

类就是对某种统一行为或特征的抽象

比如:

人类可以比作一个类,下面的男人、女人等等都继承了人类的基本特征,同时男人女人等又有各自的特殊能力,可以理解为他们各自的数据不同。

男人/女人 = 实例化

男人/女人 -> 人类(继承)

还有一个概念叫多态

多态意味着,父类的通用行为可以被子类更特殊的行为重写。

什么是实例化

书中提到了一个很有意思的描述,把实例化的过程比作蓝图复现成现实世界中的建筑。

我们也可以这样来理解实例化。

类就是规划的蓝图。

实例化就是把类变成可用对象的过程。

比如:

js 复制代码
Class Person {
    // ...
}

var man = new Person(); // 这就是实例化,这个 man 就是一个实例

类的继承

假设我们先定义一个类,然后再定义一个继承前者的类。

子类和父类的关系一目了然:

子类会包含父类行为的原始副本,但是也可以重写所有继承的行为甚至定义新行为。

多态

我们就来分析书中的例子。注意这里是伪代码哈。

js 复制代码
class Vehicle { // 这里定义一个基类
    engines = 1 // 引擎数量

    function ignition() { // 打火
        output("Turning on my engine.")
    }

    function drive() { // 启动
        ignition()
        output("Steering and moving forward!")
    }
}

class Car inherits Vehicle { // 定义一个继承了 Vehicle 的 Car 类
    wheels = 4 // 汽车是4轮驱动的

    function drive() { // 重写 drive 方法,覆盖 Vehicle 中的 drive
        inherited:drive() // 调用了基类的 drive 方法
        output("Rolling on all " + wheels + " wheels!")
    }
}

class SpeedBoat inherits Vehicle { // 定义了继承 Vehicle 的 SpeedBoat 类
    engines = 2 // 两个引擎

    function ignition() { // 覆盖了 Vehicle 的 ignition 方法
        output("Turning on my " + engines + " engines.")
    }

    function pilot() { // 模拟驾驶快艇
        inherited:drive() // 调用父类的 drive 方法
        output("Speeding through the water with ease!")
    }
}

多态性体现在 CarSpeedBoat 类对 Vehicle 类的 drive 方法的覆盖上。

Car 类通过 inherited:drive() 调用了 Vehicle 类的 drive 方法。

SpeedBoat 类虽然没有直接覆盖 drive 方法,但是在其 pilot 方法中通过 inherited:drive() 调用了 Vehicle 类的 drive 方法。

由于 SpeedBoat 类覆盖了 ignition 方法,所以 pilot 方法中的 inherited:drive() 实际上会调用 SpeedBoat 类的 ignition 方法,而不是 Vehicle 类的。

这就是多态性的一种体现:子类可以定义与父类同名的方法,在调用时,会根据对象的实际类型来执行相应的方法

最后有一点需要格外注意,我们讲述的是类的概念,但并不代表JavaScript中就能够进行类似的行为。

因为在 JavaScript 中不存在类。

混入

如果我们要把上述伪代码复现成真正的可执行JavaScript,那就需要手动模拟复制过程。

而这个模拟的过程称为混入

js 复制代码
function mixin(sourceObj, targetObj) {
    for (var key in sourceObj) {
        // 只会在不存在的情况下复制
        if (!(key in targetObj)) {
            targetObj[key] = sourceObj[key];
        }
    }
    return targetObj;
}

var Vehicle = {
    engines: 1,
    ignition: function() {
        console.log("Turning on my engine.");
    },
    drive: function() {
        this.ignition();
        console.log("Steering and moving forward!");
    }
};

var Car = mixin(Vehicle, {
    wheels: 4,
    drive: function() {
        Vehicle.drive.call(this); // 显示把 this 绑定到 Car 的上下文中
        console.log("Rolling on all " + this.wheels + " wheels!");
    }
});

我在想,这个简单地了解一下就好了,因为并不是很好的一种写代码的方式。

你要说它有啥意义...

书中描述:

混入模式(无论显式还是隐式)可以用来模拟类的复制行为,但是通常会产生丑陋并且脆弱的语法,比如显式伪多态(OtherObj.methodName.call(this, ...)),这会让代码更加难懂并且难以维护。

小结

我们简单介绍了类的概念,其实主要是面向对象的理念,比如继承、多态等等。

但其实在JavaScript中,并没有类这个东西。

我们所能做的只是尽可能模拟类的一些行为,但仍然会存在一些弊端。

我们下一章会讲到原型和原型链,留一个小小的悬念,JavaScript中真正的继承其实是通过原型链来实现的,敬请期待叭~😉😉

相关推荐
浮华似水13 分钟前
简洁之道 - React Hook Form
前端
正小安2 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
小飞猪Jay3 小时前
C++面试速通宝典——13
jvm·c++·面试
_.Switch4 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光4 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   4 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   4 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web4 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常4 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇5 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器