From f304d920b4b98ac23ceeb248c33844a2ffdd4af4 Mon Sep 17 00:00:00 2001 From: wizardforcel <562826179@qq.com> Date: Fri, 4 May 2018 20:57:14 +0800 Subject: [PATCH] 6 --- 6.md | 162 ++++++++++++++++++++++++++++------------------------ img/6-0.jpg | Bin 0 -> 27982 bytes img/6-1.svg | 13 +++++ 3 files changed, 100 insertions(+), 75 deletions(-) create mode 100644 img/6-0.jpg create mode 100644 img/6-1.svg diff --git a/6.md b/6.md index 11bd076..86cf70c 100644 --- a/6.md +++ b/6.md @@ -1,9 +1,21 @@ ## 六、对象的秘密 +> 原文:[The Secret Life of Objects](http://eloquentjavascript.net/06_object.html) +> +> 译者:[飞龙](https://github.com/wizardforcel) +> +> 协议:[CC BY-NC-SA 4.0](http://creativecommons.org/licenses/by-nc-sa/4.0/) +> +> 自豪地采用[谷歌翻译](https://translate.google.cn/) +> +> 部分参考了[《JavaScript 编程精解(第 2 版)》](https://book.douban.com/subject/26707144/) + > 抽象数据类型是通过编写一种特殊的程序来实现的,该程序根据可在其上执行的操作来定义类型。 > > Barbara Liskov,《Programming with Abstract Data Types》 +![](img/6-0.jpg) + 第 4 章介绍了 JavaScript 的对象(object)。 在编程文化中,我们有一个名为面向对象编程(OOP)的东西,这是一组技术,使用对象(和相关概念)作为程序组织的中心原则。 虽然没有人真正同意其精确定义,但面向对象编程已经成为了许多编程语言的设计,包括 JavaScript 在内。 本章将描述这些想法在 JavaScript 中的应用方式。 @@ -28,7 +40,7 @@ 方法不过是持有函数值的属性。 这是一个简单的方法: -``` +```js let rabbit = {}; rabbit.speak = function(line) { console.log(`The rabbit says '${line}'`); @@ -40,7 +52,7 @@ rabbit.speak("I'm alive."); 方法通常会在对象被调用时执行一些操作。将函数作为对象的方法调用时,会找到对象中对应的属性并直接调用。当函数作为方法调用时,函数体内叫做`this`的绑定自动指向在它上面调用的对象。 -``` +```js function speak(line) { console.log(`The ${this.type} rabbit says '${line}'`); } @@ -57,18 +69,18 @@ hungryRabbit.speak("I could use a carrot right now."); 你可以把`this`看作是以不同方式传递的额外参数。 如果你想显式传递它,你可以使用函数的`call`方法,它接受`this`值作为第一个参数,并将其它处理为看做普通参数。 -``` +```js speak.call(hungryRabbit, "Burp!"); // → The hungry rabbit says 'Burp!' ``` -这段代码使用了关键字this来输出正在说话的兔子的种类。我们回想一下apply和bind方法,这两个方法接受的第一个参数可以用来模拟对象中方法的调用。这两个方法会把第一个参数复制给this。 +这段代码使用了关键字`this`来输出正在说话的兔子的种类。我们回想一下`apply`和`bind`方法,这两个方法接受的第一个参数可以用来模拟对象中方法的调用。这两个方法会把第一个参数复制给`this`。 由于每个函数都有自己的`this`绑定,它的值依赖于它的调用方式,所以在用`function`关键字定义的常规函数中,不能引用外层作用域的`this`。 箭头函数是不同的 - 它们不绑定他们自己的`this`,但可以看到他们周围(定义位置)作用域的`this`绑定。 因此,你可以像下面的代码那样,在局部函数中引用`this`: -``` +```js function normalize() { console.log(this.coords.map(n => n / this.length)); } @@ -82,7 +94,7 @@ normalize.call({coords: [0, 2, 3], length: 5}); 我们来仔细看看以下这段代码。 -``` +```js let empty = {}; console.log(empty.toString); // → function toString(){…} @@ -92,11 +104,11 @@ console.log(empty.toString()); 我从一个空对象中取出了一个属性。 好神奇! -实际上并非如此。我只是掩盖了一些JavaScript对象的内部工作细节罢了。每个对象除了拥有自己的属性外,都包含一个原型(prototype)。原型是另一个对象,是对象的一个属性来源。当开发人员访问一个对象不包含的属性时,就会从对象原型中搜索属性,接着是原型的原型,依此类推。 +实际上并非如此。我只是掩盖了一些 JavaScript 对象的内部工作细节罢了。每个对象除了拥有自己的属性外,都包含一个原型(prototype)。原型是另一个对象,是对象的一个属性来源。当开发人员访问一个对象不包含的属性时,就会从对象原型中搜索属性,接着是原型的原型,依此类推。 -那么空对象的原型是什么呢?是Object.prototype,它是所有对象中原型的父原型。 +那么空对象的原型是什么呢?是`Object.prototype`,它是所有对象中原型的父原型。 -``` +```js console.log(Object.getPrototypeOf({}) == Object.prototype); // → true @@ -106,11 +118,11 @@ console.log(Object.getPrototypeOf(Object.prototype)); 正如你的猜测,`Object.getPrototypeOf`返回一个对象的原型。 -JavaScript对象原型的关系是一种树形结构,整个树形结构的根部就是Object.prototype。Object.prototype提供了一些可以在所有对象中使用的方法。比如说,toString方法可以将一个对象转换成其字符串表示形式。 +JavaScript 对象原型的关系是一种树形结构,整个树形结构的根部就是`Object.prototype`。`Object.prototype`提供了一些可以在所有对象中使用的方法。比如说,`toString`方法可以将一个对象转换成其字符串表示形式。 -许多对象并不直接将Object.prototype作为其原型,而会使用另一个原型对象,用于提供一系列不同的默认属性。函数继承自Function.prototype,而数组继承自Array.prototype。 +许多对象并不直接将`Object.prototype`作为其原型,而会使用另一个原型对象,用于提供一系列不同的默认属性。函数继承自`Function.prototype`,而数组继承自`Array.prototype`。 -``` +```js console.log(Object.getPrototypeOf(Math.max) == Function.prototype); // → true @@ -119,11 +131,11 @@ console.log(Object.getPrototypeOf([]) == // → true ``` -对于这样的原型对象来说,其自身也包含了一个原型对象,通常情况下是Object.prototype,所以说,这些原型对象可以间接提供toString这样的方法。 +对于这样的原型对象来说,其自身也包含了一个原型对象,通常情况下是`Object.prototype`,所以说,这些原型对象可以间接提供`toString`这样的方法。 你可以使用`Object.create`来创建一个具有特定原型的对象。 -``` +```js let protoRabbit = { speak(line) { console.log(`The ${this.type} rabbit says '${line}'`); @@ -137,7 +149,7 @@ killerRabbit.speak("SKREEEE!"); 像对象表达式中的`speak(line)`这样的属性是定义方法的简写。 它创建了一个名为`speak`的属性,并向其提供函数作为它的值。 -原型对象protoRabbit是一个容器,用于包含所有兔子对象的公有属性。每个独立的兔子对象(比如killerRabbit)可以包含其自身属性(比如本例中的type属性),也可以派生其原型对象中公有的属性。 +原型对象`protoRabbit`是一个容器,用于包含所有兔子对象的公有属性。每个独立的兔子对象(比如`killerRabbit`)可以包含其自身属性(比如本例中的`type`属性),也可以派生其原型对象中公有的属性。 ### 类 @@ -147,7 +159,7 @@ JavaScript 的原型系统可以解释为对一种面向对象的概念(称为 所以为了创建一个给定类的实例,你必须使对象从正确的原型派生,但是你也必须确保,它本身具有这个类的实例应该具有的属性。 这是构造器(constructor)函数的作用。 -``` +```js function makeRabbit(type) { let rabbit = Object.create(protoRabbit); rabbit.type = type; @@ -159,7 +171,7 @@ JavaScript 提供了一种方法,来使得更容易定义这种类型的功能 构造对象时使用的原型对象,可以通过构造器的`prototype`属性来查找。 -``` +```js function Rabbit(type) { this.type = type; } @@ -170,13 +182,13 @@ Rabbit.prototype.speak = function(line) { let weirdRabbit = new Rabbit("weird"); ``` -构造器(实际上是所有函数)都会自动获得一个名为`prototype`的属性,默认情况下它包含一个普通的,来自`Object.prototype`的空对象。 如果需要,可以用新对象覆盖它。 或者,您可以将属性添加到现有对象,如示例所示。 +构造器(实际上是所有函数)都会自动获得一个名为`prototype`的属性,默认情况下它包含一个普通的,来自`Object.prototype`的空对象。 如果需要,可以用新对象覆盖它。 或者,你可以将属性添加到现有对象,如示例所示。 按照惯例,构造器的名字是大写的,这样它们可以很容易地与其他函数区分开来。 重要的是,理解原型与构造器关联的方式(通过其`prototype`属性),与对象拥有原型(可以通过`Object.getPrototypeOf`查找)的方式之间的区别。 构造器的实际原型是`Function.prototype`,因为构造器是函数。 它的`prototype`属性拥有原型,用于通过它创建的实例。 -``` +```js console.log(Object.getPrototypeOf(Rabbit) == Function.prototype); // → true @@ -189,7 +201,7 @@ console.log(Object.getPrototypeOf(weirdRabbit) == 所以 JavaScript 类是带有原型属性的构造器。 这就是他们的工作方式,直到 2015 年,这就是你编写他们的方式。 最近,我们有了一个不太笨拙的表示法。 -``` +```js class Rabbit { constructor(type) { this.type = type; @@ -205,11 +217,11 @@ let blackRabbit = new Rabbit("black"); `class`关键字是类声明的开始,它允许我们在一个地方定义一个构造器和一组方法。 可以在声明的大括号内写入任意数量的方法。 一个名为`constructor`的对象受到特别处理。 它提供了实际的构造器,它将绑定到名称`"Rabbit"`。 其他函数被打包到该构造器的原型中。 因此,上面的类声明等同于上一节中的构造器定义。 它看起来更好。 -类声明目前只允许方法 - 持有函数的属性 - 添加到原型中。 当你想在那里保存一个非函数值时,这可能会有点不方便。 该语言的下一个版本可能会改善这一点。 现在,您可以在定义该类后直接操作原型来创建这些属性。 +类声明目前只允许方法 - 持有函数的属性 - 添加到原型中。 当你想在那里保存一个非函数值时,这可能会有点不方便。 该语言的下一个版本可能会改善这一点。 现在,你可以在定义该类后直接操作原型来创建这些属性。 -像`function`一样,`class`可以在语句和表达式中使用。 当用作表达式时,它没有定义绑定,而只是将构造函数作为一个值生成。 您可以在类表达式中省略类名称。 +像`function`一样,`class`可以在语句和表达式中使用。 当用作表达式时,它没有定义绑定,而只是将构造器作为一个值生成。 你可以在类表达式中省略类名称。 -``` +```js let object = new class { getWord() { return "hello"; } }; console.log(object.getWord()); // → hello @@ -219,7 +231,7 @@ console.log(object.getWord()); 将属性添加到对象时,无论它是否存在于原型中,该属性都会添加到对象本身中。 如果原型中已经有一个同名的属性,该属性将不再影响对象,因为它现在隐藏在对象自己的属性后面。 -``` +```js Rabbit.prototype.teeth = "small"; console.log(killerRabbit.teeth); // → small @@ -232,15 +244,15 @@ console.log(Rabbit.prototype.teeth); // → small ``` -下图简单地描述了代码执行后的情况。其中Rabbit和Object原型画在了killerRabbit之下,我们可以从原型中找到对象中没有的属性。 +下图简单地描述了代码执行后的情况。其中`Rabbit`和`Object`原型画在了`killerRabbit`之下,我们可以从原型中找到对象中没有的属性。 -![](../Images/00204.jpeg) +![](img/6-1.svg) -覆盖原型中存在的属性是很有用的特性。就像示例展示的那样,我们覆盖了killerRabbit的teeth属性,这可以用来描述实例(对象中更为泛化的类的实例)的特殊属性,同时又可以让简单对象从原型中获取标准的值。 +覆盖原型中存在的属性是很有用的特性。就像示例展示的那样,我们覆盖了`killerRabbit`的`teeth`属性,这可以用来描述实例(对象中更为泛化的类的实例)的特殊属性,同时又可以让简单对象从原型中获取标准的值。 覆盖也用于向标准函数和数组原型提供`toString`方法,与基本对象的原型不同。 -``` +```js console.log(Array.prototype.toString == Object.prototype.toString); // → false @@ -248,9 +260,9 @@ console.log([1, 2].toString()); // → 1,2 ``` -调用数组的toString方法后得到的结果与调用.join(“,”)的结果十分类似,即在数组的每个值之间插入一个逗号。而直接使用数组调用Object.prototype.toString则会产生一个完全不同的字符串。由于Object原型提供的toString方法并不了解数组结构,因此只会简单地输出一对方括号,并在方括号中间输出单词“object”和类型的名称。 +调用数组的`toString`方法后得到的结果与调用`.join(",")`的结果十分类似,即在数组的每个值之间插入一个逗号。而直接使用数组调用`Object.prototype.toString`则会产生一个完全不同的字符串。由于`Object`原型提供的`toString`方法并不了解数组结构,因此只会简单地输出一对方括号,并在方括号中间输出单词`"object"`和类型的名称。 -``` +```js console.log(Object.prototype.toString.call([1, 2])); // → [object Array] ``` @@ -259,9 +271,9 @@ console.log(Object.prototype.toString.call([1, 2])); 我们在上一章中看到了映射(map)这个词,用于一个操作,通过对元素应用函数来转换数据结构。 令人困惑的是,在编程时,同一个词也被用于相关而不同的事物。 -映射(名词)是将值(键)与其他值相关联的数据结构。 例如,您可能想要将姓名映射到年龄。 为此可以使用对象。 +映射(名词)是将值(键)与其他值相关联的数据结构。 例如,你可能想要将姓名映射到年龄。 为此可以使用对象。 -``` +```js let ages = { Boris: 39, Liang: 22, @@ -280,7 +292,7 @@ console.log("Is toString's age known?", "toString" in ages); 因此,使用简单对象作为映射是危险的。 有几种可能的方法来避免这个问题。 首先,可以使用`null`原型创建对象。 如果将`null`传递给`Object.create`,那么所得到的对象将不会从`Object.prototype`派生,并且可以安全地用作映射。 -``` +```js console.log("toString" in Object.create(null)); // → false ``` @@ -289,7 +301,7 @@ console.log("toString" in Object.create(null)); 幸运的是,JavaScript 带有一个叫做`Map`的类,它正是为了这个目的而编写。 它存储映射并允许任何类型的键。 -``` +```js let ages = new Map(); ages.set("Boris", 39); ages.set("Liang", 22); @@ -304,9 +316,9 @@ console.log(ages.has("toString")); `set`,`get`和`has`方法是`Map`对象的接口的一部分。 编写一个可以快速更新和搜索大量值的数据结构并不容易,但我们不必担心这一点。 其他人为我们实现,我们可以通过这个简单的接口来使用他们的工作。 -如果您确实有一个简单对象,出于某种原因需要将它视为一个映射,那么了解`Object.keys`只返回对象的自己的键,而不是原型中的那些键,会很有用。 作为`in`运算符的替代方法,您可以使用`hasOwnProperty`方法,该方法会忽略对象的原型。 +如果你确实有一个简单对象,出于某种原因需要将它视为一个映射,那么了解`Object.keys`只返回对象的自己的键,而不是原型中的那些键,会很有用。 作为`in`运算符的替代方法,你可以使用`hasOwnProperty`方法,该方法会忽略对象的原型。 -``` +```js console.log({x: 1}.hasOwnProperty("x")); // → true console.log({x: 1}.hasOwnProperty("toString")); @@ -317,7 +329,7 @@ console.log({x: 1}.hasOwnProperty("toString")); 当你调用一个对象的`String`函数(将一个值转换为一个字符串)时,它会调用该对象的`toString`方法来尝试从它创建一个有意义的字符串。 我提到一些标准原型定义了自己的`toString`版本,因此它们可以创建一个包含比`"[object Object]"`有用信息更多的字符串。 你也可以自己实现。 -``` +```js Rabbit.prototype.toString = function() { return `a ${this.type} rabbit`; }; @@ -338,9 +350,9 @@ console.log(String(blackRabbit)); 这是一个坏主意,这个问题并不常见。 大多数 JavaScript 程序员根本就不会去想它。 但是,语言设计师们正在思考这个问题,无论如何都为我们提供了解决方案。 -当我声称属性名称是字符串时,这并不完全准确。 他们通常是,但他们也可以是符号(symbol)。 符号是使用`Symbol`函数创建的值。 与字符串不同,新创建的符号是唯一的 - 您不能两次创建相同的符号。 +当我声称属性名称是字符串时,这并不完全准确。 他们通常是,但他们也可以是符号(symbol)。 符号是使用`Symbol`函数创建的值。 与字符串不同,新创建的符号是唯一的 - 你不能两次创建相同的符号。 -``` +```js let sym = Symbol("name"); console.log(sym == Symbol("name")); // → false @@ -353,7 +365,7 @@ console.log(blackRabbit[sym]); 由于符号既独特又可用于属性名称,因此符号适合定义可以和其他属性共生的接口,无论它们的名称是什么。 -``` +```js const toStringSymbol = Symbol("toString"); Array.prototype[toStringSymbol] = function() { return `${this.length} cm of blue yarn`; @@ -366,7 +378,7 @@ console.log([1, 2][toStringSymbol]()); 通过在属性名称周围使用方括号,可以在对象表达式和类中包含符号属性。 这会导致属性名称的求值,就像方括号属性访问表示法一样,这允许我们引用一个持有该符号的绑定。 -``` +```js let stringObject = { [toStringSymbol]() { return "a jute rope"; } }; @@ -384,7 +396,7 @@ console.log(stringObject[toStringSymbol]()); 我们可以直接使用这个接口。 -``` +```js let okIterator = "OK"[Symbol.iterator](); console.log(okIterator.next()); // → {value: "O", done: false} @@ -396,7 +408,7 @@ console.log(okIterator.next()); 我们来实现一个可迭代的数据结构。 我们将构建一个`matrix`类,充当一个二维数组。 -``` +```js class Matrix { constructor(width, height, element = (x, y) => undefined) { this.width = width; @@ -419,12 +431,12 @@ class Matrix { 该类将其内容存储在`width × height`个元素的单个数组中。 元素是按行存储的,因此,例如,第五行中的第三个元素存储在位置`4 × width + 2`中(使用基于零的索引)。 -构造函数需要宽度,高度和一个可选的内容函数,用来填充初始值。 `get`和`set`方法用于检索和更新矩阵中的元素。 +构造器需要宽度,高度和一个可选的内容函数,用来填充初始值。 `get`和`set`方法用于检索和更新矩阵中的元素。 遍历矩阵时,通常对元素的位置以及元素本身感兴趣,所以我们会让迭代器产生具有`x`,`y`和`value`属性的对象。 -``` +```js class MatrixIterator { constructor(matrix) { this.x = 0; @@ -451,7 +463,7 @@ class MatrixIterator { 让我们使`Matrix`类可迭代。 在本书中,我会偶尔使用事后的原型操作来为类添加方法,以便单个代码段保持较小且独立。 在一个正常的程序中,不需要将代码分成小块,而是直接在`class`中声明这些方法。 -``` +```js Matrix.prototype[Symbol.iterator] = function() { return new MatrixIterator(this); }; @@ -459,7 +471,7 @@ Matrix.prototype[Symbol.iterator] = function() { 现在我们可以用`for/of`来遍历一个矩阵。 -``` +```js let matrix = new Matrix(2, 2, (x, y) => `value ${x},${y}`); for (let {x, y, value} of matrix) { console.log(x, y, value); @@ -476,7 +488,7 @@ for (let {x, y, value} of matrix) { 这样的对象甚至不需要直接在实例中计算和存储这样的属性。 即使直接访问的属性也可能隐藏了方法调用。 这种方法称为读取器(getter),它们通过在方法名称前面编写`get`来定义。 -``` +```js let varyingSize = { get size() { return Math.floor(Math.random() * 100); @@ -491,7 +503,7 @@ console.log(varyingSize.size); 每当有人读取此对象的`size`属性时,就会调用相关的方法。 当使用写入器(setter)写入属性时,可以做类似的事情。 -``` +```js class Temperature { constructor(celsius) { this.celsius = celsius; @@ -515,11 +527,11 @@ console.log(temp.celsius); // → 30 ``` -`Temperature`类允许您以摄氏度或华氏度读取和写入温度,但内部仅存储摄氏度,并在`fahrenheit`读写器中自动转换为摄氏度。 +`Temperature`类允许你以摄氏度或华氏度读取和写入温度,但内部仅存储摄氏度,并在`fahrenheit`读写器中自动转换为摄氏度。 -有时候你想直接向你的构造函数附加一些属性,而不是原型。 这样的方法将无法访问类实例,但可以用来提供额外方法来创建实例。 +有时候你想直接向你的构造器附加一些属性,而不是原型。 这样的方法将无法访问类实例,但可以用来提供额外方法来创建实例。 -在类声明内部,名称前面写有`static`的方法,存储在构造函数中。 所以`Temperature`类可以让你写出`Temperature.fromFahrenheit(100)`,来使用华氏温度创建一个温度。 +在类声明内部,名称前面写有`static`的方法,存储在构造器中。 所以`Temperature`类可以让你写出`Temperature.fromFahrenheit(100)`,来使用华氏温度创建一个温度。 ## 继承 @@ -531,7 +543,7 @@ JavaScript 的原型系统可以创建一个新类,就像旧类一样,但是 在面向对象的编程术语中,这称为继承(inheritance)。 新类继承旧类的属性和行为。 -``` +```js class SymmetricMatrix extends Matrix { constructor(size, element = (x, y) => undefined) { super(size, size, (x, y) => { @@ -554,19 +566,19 @@ console.log(matrix.get(2, 3)); `extends`这个词用于表示,这个类不应该直接基于默认的`Object`原型,而应该基于其他类。 这被称为超类(superclass)。 派生类是子类(subclass)。 -为了初始化`SymmetricMatrix`实例,构造函数通过`super`关键字调用其超类的构造函数。 这是必要的,因为如果这个新对象的行为(大致)像`Matrix`,它需要矩阵具有的实例属性。 为了确保矩阵是对称的,构造函数包装了`content`方法,来交换对角线以下的值的坐标。 +为了初始化`SymmetricMatrix`实例,构造器通过`super`关键字调用其超类的构造器。 这是必要的,因为如果这个新对象的行为(大致)像`Matrix`,它需要矩阵具有的实例属性。 为了确保矩阵是对称的,构造器包装了`content`方法,来交换对角线以下的值的坐标。 -`set`方法再次使用`super`,但这次不是调用构造函数,而是从超类的一组方法中调用特定的方法。 我们正在重新定义`set`,但是想要使用原来的行为。 因为`this.set`引用新的`set`方法,所以调用这个方法是行不通的。 在类方法内部,`super`提供了一种方法,来调用超类中定义的方法。 +`set`方法再次使用`super`,但这次不是调用构造器,而是从超类的一组方法中调用特定的方法。 我们正在重新定义`set`,但是想要使用原来的行为。 因为`this.set`引用新的`set`方法,所以调用这个方法是行不通的。 在类方法内部,`super`提供了一种方法,来调用超类中定义的方法。 继承允许我们用相对较少的工作,从现有数据类型构建稍微不同的数据类型。 它是面向对象传统的基础部分,与封装和多态一样。 尽管后两者现在普遍被认为是伟大的想法,但继承更具争议性。 尽管封装和多态可用于将代码彼此分离,从而减少整个程序的耦合,但继承从根本上将类连接在一起,从而产生更多的耦合。 继承一个类时,比起单纯使用它,你通常必须更加了解它如何工作。 继承可能是一个有用的工具,并且我现在在自己的程序中使用它,但它不应该成为你的第一个工具,你可能不应该积极寻找机会来构建类层次结构(类的家族树)。 -### 6.12 instanceof运算符 +### 6.12 `instanceof`运算符 -在有些时候,了解某个对象是否继承自某个特定类,也是十分有用的。JavaScript 为此提供了一个二元运算符,名为instanceof。 +在有些时候,了解某个对象是否继承自某个特定类,也是十分有用的。JavaScript 为此提供了一个二元运算符,名为`instanceof`。 -``` +```js console.log( new SymmetricMatrix(2) instanceof SymmetricMatrix); // → true @@ -578,17 +590,17 @@ console.log([1] instanceof Array); // → true ``` -该运算符会浏览所有继承类型。所以`SymmetricMatrix`是`Matrix`的一个实例。 该运算符也可以应用于像`Array`这样的标准构造函数。 几乎每个对象都是`Object`的一个实例。 +该运算符会浏览所有继承类型。所以`SymmetricMatrix`是`Matrix`的一个实例。 该运算符也可以应用于像`Array`这样的标准构造器。 几乎每个对象都是`Object`的一个实例。 ### 本章小结 -对象不仅仅持有它们自己的属性。对象中有另一个对象:原型,只要原型中包含了属性,那么根据原型构造出来的对象也就可以看成包含了相应的属性。简单对象直接以Object.prototype作为原型。 +对象不仅仅持有它们自己的属性。对象中有另一个对象:原型,只要原型中包含了属性,那么根据原型构造出来的对象也就可以看成包含了相应的属性。简单对象直接以`Object.prototype`作为原型。 -构造函数是名称通常以大写字母开头的函数,可以与`new`运算符一起使用来创建新对象。 新对象的原型是构造函数的`prototype`属性中的对象。 通过将属性放到它们的原型中,可以充分利用这一点,给定类型的所有值在原型中分享它们的属性。 `class`表示法提供了一个显式方法,来定义一个构造函数及其原型。 +构造器是名称通常以大写字母开头的函数,可以与`new`运算符一起使用来创建新对象。 新对象的原型是构造器的`prototype`属性中的对象。 通过将属性放到它们的原型中,可以充分利用这一点,给定类型的所有值在原型中分享它们的属性。 `class`表示法提供了一个显式方法,来定义一个构造器及其原型。 -您可以定义读写器,在每次访问对象的属性时秘密地调用方法。 静态方法是存储在类的构造函数,而不是其原型中的方法。 +你可以定义读写器,在每次访问对象的属性时秘密地调用方法。 静态方法是存储在类的构造器,而不是其原型中的方法。 -给定一个对象和一个构造函数,`instanceof`运算符可以告诉你该对象是否是该构造函数的一个实例。 +给定一个对象和一个构造器,`instanceof`运算符可以告诉你该对象是否是该构造器的一个实例。 可以使用对象的来做一个有用的事情是,为它们指定一个接口,告诉每个人他们只能通过该接口与对象通信。 构成对象的其余细节,现在被封装在接口后面。 @@ -600,13 +612,13 @@ console.log([1] instanceof Array); #### 6.14.1 向量类型 -编写一个构造器Vec,在二维空间中表示数组。该函数接受两个数字参数x和y,并将其保存到对象的同名属性中。 +编写一个构造器`Vec`,在二维空间中表示数组。该函数接受两个数字参数`x`和`y`,并将其保存到对象的同名属性中。 -向Vec原型添加两个方法:plus和minus,它们接受另一个向量作为参数,分别返回两个向量(一个是this,另一个是参数)的和向量与差向量。 +向`Vec`原型添加两个方法:`plus`和`minus`,它们接受另一个向量作为参数,分别返回两个向量(一个是`this`,另一个是参数)的和向量与差向量。 -向原型添加一个getter属性length,用于计算向量长度,即点(x,y)与原点(0,0)之间的距离。 +向原型添加一个`getter`属性`length`,用于计算向量长度,即点`(x,y)`与原点`(0,0)`之间的距离。 -``` +```js // Your code here. console.log(new Vec(1, 2).plus(new Vec(2, 3))); @@ -621,13 +633,13 @@ console.log(new Vec(3, 4).length); 标准的 JavaScript 环境提供了另一个名为`Set`的数据结构。 像`Map`的实例一样,集合包含一组值。 与`Map`不同,它不会将其他值与这些值相关联 - 它只会跟踪哪些值是该集合的一部分。 一个值只能是一个集合的一部分 - 再次添加它没有任何作用。 -写一个名为`Group`的类(因为`Set`已被占用)。 像`Set`一样,它具有`add`,`delete`和`has`方法。 它的构造函数创建一个空的分组,`add`给分组添加一个值(但仅当它不是成员时),`delete`从组中删除它的参数(如果它是成员),`has` 返回一个布尔值,表明其参数是否为分组的成员。 +写一个名为`Group`的类(因为`Set`已被占用)。 像`Set`一样,它具有`add`,`delete`和`has`方法。 它的构造器创建一个空的分组,`add`给分组添加一个值(但仅当它不是成员时),`delete`从组中删除它的参数(如果它是成员),`has` 返回一个布尔值,表明其参数是否为分组的成员。 使用`===`运算符或类似于`indexOf`的东西来确定两个值是否相同。 为该类提供一个静态的`from`方法,该方法接受一个可迭代的对象作为参数,并创建一个分组,包含遍历它产生的所有值。 -``` +```js // Your code here. class Group { @@ -646,13 +658,13 @@ console.log(group.has(10)); #### 可迭代分组 -使上一个练习中的`Group`类可迭代。 如果您不清楚接口的确切形式,请参阅本章前面迭代器接口的章节。 +使上一个练习中的`Group`类可迭代。 如果你不清楚接口的确切形式,请参阅本章前面迭代器接口的章节。 -如果您使用数组来表示分组的成员,则不要仅仅通过调用数组中的`Symbol.iterator`方法来返回迭代器。 这会起作用,但它会破坏这个练习的目的。 +如果你使用数组来表示分组的成员,则不要仅仅通过调用数组中的`Symbol.iterator`方法来返回迭代器。 这会起作用,但它会破坏这个练习的目的。 -如果分组被修改时,您的迭代器在迭代过程中出现奇怪的行为,那也没问题。 +如果分组被修改时,你的迭代器在迭代过程中出现奇怪的行为,那也没问题。 -``` +```js // Your code here (and the code from the previous exercise) for (let value of Group.from(["a", "b", "c"])) { @@ -665,11 +677,11 @@ for (let value of Group.from(["a", "b", "c"])) { ## 借鉴方法 -在本章前面我提到,当你想忽略原型的属性时,对象的`hasOwnProperty`可以用作`in`运算符的更强大的替代方法。 但是如果你的映射需要包含`hasOwnProperty`这个词呢? 您将无法再调用该方法,因为对象的属性隐藏了方法值。 +在本章前面我提到,当你想忽略原型的属性时,对象的`hasOwnProperty`可以用作`in`运算符的更强大的替代方法。 但是如果你的映射需要包含`hasOwnProperty`这个词呢? 你将无法再调用该方法,因为对象的属性隐藏了方法值。 你能想到一种方法,对拥有自己的同名属性的对象,调用`hasOwnProperty`吗? -``` +```js let map = {one: true, two: true, hasOwnProperty: true}; // Fix this call console.log(map.hasOwnProperty("one")); diff --git a/img/6-0.jpg b/img/6-0.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8af17dbc5777ee992850be7f6fab2115b3cbc054 GIT binary patch literal 27982 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 y%XBuCIzW52QF|5 + +toString: <function>...teeth: "small"speak: <function>killerRabbitteeth: "long, sharp, ..."type: "killer"RabbitprototypeObjectcreate: <function>prototype...