摘要:当我们在开发某些东西时,经常会需要我们自己的 error 类来反映在我们的任务中可能出错的特定任务。对于网络操作中的 error,我们需要 HttpError,对于数据库操作中的 error,我们需要 DbError,对于搜索操作中的 error,我们需要 NotFoundError,等等。 我们自
阅读全文
摘要:不管你多么精通编程,有时我们的脚本总还是会出现错误。可能是因为我们的编写出错,或是与预期不同的用户输入,或是错误的服务端响应以及其他数千种原因。 通常,如果发生错误,脚本就会“死亡”(立即停止),并在控制台将错误打印出来。 但是有一种语法结构 try...catch,它使我们可以“捕获(catch)
阅读全文
摘要:在 JavaScript 中,我们只能继承单个对象。每个对象只能有一个 [[Prototype]]。并且每个类只可以扩展另外一个类。 但是有些时候这种设定(译注:单继承)会让人感到受限制。例如,我有一个 StreetSweeper 类和一个 Bicycle 类,现在想要一个它们的 mixin:Str
阅读全文
摘要:instanceof 操作符用于检查一个对象是否属于某个特定的 class。同时,它还考虑了继承。 在许多情况下,可能都需要进行此类检查。例如,它可以被用来构建一个 多态性(polymorphic) 的函数,该函数根据参数的类型对参数进行不同的处理。 instanceof 操作符 语法: obj i
阅读全文
摘要:内建的类,例如 Array,Map 等也都是可以扩展的(extendable)。 例如,这里有一个继承自原生 Array 的类 PowerArray: // 给 PowerArray 新增了一个方法(可以增加更多) class PowerArray extends Array { isEmpty()
阅读全文
摘要:面向对象编程最重要的原则之一 —— 将内部接口与外部接口分隔开来。 在开发比 “hello world” 应用程序更复杂的东西时,这是“必须”遵守的做法。 为了理解这一点,让我们脱离开发过程,把目光转向现实世界。 通常,我们使用的设备都非常复杂。但是,将内部接口与外部接口分隔开来可以让我们使用它们且
阅读全文
摘要:我们可以把一个方法作为一个整体赋值给类。这样的方法被称为 静态的(static)。 在一个类的声明中,它们以 static 关键字开头,如下所示: class User { static staticMethod() { console.log(this User); } } User.static
阅读全文
摘要:类继承是一个类扩展另一个类的一种方式。 因此,我们可以在现有功能之上创建新功能。 “extends” 关键字 假设我们有 class Animal: class Animal { constructor(name) { this.speed = 0; this.name = name; } run(
阅读全文
摘要:在日常开发中,我们经常需要创建许多相同类型的对象,例如用户(users)、商品(goods)或者任何其他东西。 正如我们在 构造器和操作符 "new" 一章中已经学到的,new function 可以帮助我们实现这种需求。 但在现代 JavaScript 中,还有一个更高级的“类(class)”构造
阅读全文
摘要:在这部分内容的第一章中,我们提到了设置原型的现代方法。 使用 obj.__proto__ 设置或读取原型被认为已经过时且不推荐使用(deprecated)了(已经被移至 JavaScript 规范的附录 B,意味着仅适用于浏览器)。 现代的获取/设置原型的方法有: Object.getPrototy
阅读全文
摘要:"prototype" 属性在 JavaScript 自身的核心部分中被广泛地应用。所有的内建构造函数都用到了它。 首先,我们将看看原生原型的详细信息,然后学习如何使用它为内建对象添加新功能。 Object.prototype 假如我们输出一个空对象: let obj = {}; console.l
阅读全文
摘要:我们还记得,可以使用诸如 new F() 这样的构造函数来创建一个新对象。 如果 F.prototype 是一个对象,那么 new 操作符会使用它为新对象设置 [[Prototype]]。 ❗️ 请注意: JavaScript 从一开始就有了原型继承。这是 JavaScript 编程语言的核心特性之
阅读全文
摘要:在编程中,我们经常会想获取并扩展一些东西。 例如,我们有一个 user 对象及其属性和方法,并希望将 admin 和 guest 作为基于 user 稍加修改的变体。我们想重用 user 中的内容,而不是复制/重新实现它的方法,而只是在其之上构建一个新的对象。 原型继承(Prototypal inh
阅读全文
摘要:有两种类型的对象属性。 第一种是 数据属性。我们已经知道如何使用它们了。到目前为止,我们使用过的所有属性都是数据属性。 第二种类型的属性是新东西。它是 访问器属性(accessor property)。它们本质上是用于获取和设置值的函数,但从外部代码来看就像常规属性。 getter 和 setter
阅读全文
摘要:我们知道,对象可以存储属性。 到目前为止,属性对我们来说只是一个简单的“键值”对。但对象属性实际上是更灵活且更强大的东西。 在本章中,我们将学习其他配置选项,在下一章中,我们将学习如何将它们无形地转换为 getter/setter 函数。 属性标志 对象属性(properties),除 value
阅读全文
摘要:让我们深入研究一下箭头函数。 箭头函数不仅仅是编写简洁代码的“捷径”。它还具有非常特殊且有用的特性。 JavaScript 充满了我们需要编写在其他地方执行的小函数的情况。 例如: arr.forEach(func) —— forEach 对每个数组元素都执行 func。 setTimeout(fu
阅读全文
摘要:当将对象方法作为回调进行传递,例如传递给 setTimeout,这儿会存在一个常见的问题:“丢失 this”。 在本章中,我们会学习如何去解决这个问题。 丢失 “this” 我们已经看到了丢失 this 的例子。一旦方法被传递到与对象分开的某个地方 —— this 就丢失。 下面是使用 setTim
阅读全文
摘要:JavaScript 在处理函数时提供了非凡的灵活性。它们可以被传递,用作对象,现在我们将看到如何在它们之间 转发(forward) 调用并 装饰(decorate) 它们。 透明缓存 假设我们有一个 CPU 重负载的函数 slow(x),但它的结果是稳定的。换句话说,对于相同的 x,它总是返回相同
阅读全文
摘要:有时我们并不想立即执行一个函数,而是等待特定一段时间之后再执行。这就是所谓的“计划调用(scheduling a call)”。 目前有两种方式可以实现: setTimeout 允许我们将函数推迟到一段时间间隔之后再执行。 setInterval 允许我们重复运行一个函数,从一段时间间隔之后开始运行
阅读全文
摘要:还有一种创建函数的方法。它很少被使用,但有些时候只能选择它。 语法 创建函数的语法: let func = new Function ([arg1, arg2, ...argN], functionBody); 该函数是通过使用参数 arg1...argN 和给定的 functionBody 创建的
阅读全文