mirror of
https://github.com/apachecn/eloquent-js-3e-zh.git
synced 2025-05-23 20:02:20 +00:00
6
This commit is contained in:
parent
f304d920b4
commit
1a0830d30f
28
6.md
28
6.md
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
虽然没有人真正同意其精确定义,但面向对象编程已经成为了许多编程语言的设计,包括 JavaScript 在内。 本章将描述这些想法在 JavaScript 中的应用方式。
|
虽然没有人真正同意其精确定义,但面向对象编程已经成为了许多编程语言的设计,包括 JavaScript 在内。 本章将描述这些想法在 JavaScript 中的应用方式。
|
||||||
|
|
||||||
### 封装
|
## 封装
|
||||||
|
|
||||||
面向对象编程的核心思想是将程序分成小型片段,并让每个片段负责管理自己的状态。
|
面向对象编程的核心思想是将程序分成小型片段,并让每个片段负责管理自己的状态。
|
||||||
|
|
||||||
@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
将接口与实现分离是一个好主意。 它通常被称为封装(encapsulation)。
|
将接口与实现分离是一个好主意。 它通常被称为封装(encapsulation)。
|
||||||
|
|
||||||
### 6.2 方法
|
## 方法
|
||||||
|
|
||||||
方法不过是持有函数值的属性。 这是一个简单的方法:
|
方法不过是持有函数值的属性。 这是一个简单的方法:
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ normalize.call({coords: [0, 2, 3], length: 5});
|
|||||||
|
|
||||||
如果我使用`function`关键字将参数写入`map`,则代码将不起作用。
|
如果我使用`function`关键字将参数写入`map`,则代码将不起作用。
|
||||||
|
|
||||||
### 原型
|
## 原型
|
||||||
|
|
||||||
我们来仔细看看以下这段代码。
|
我们来仔细看看以下这段代码。
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ killerRabbit.speak("SKREEEE!");
|
|||||||
|
|
||||||
原型对象`protoRabbit`是一个容器,用于包含所有兔子对象的公有属性。每个独立的兔子对象(比如`killerRabbit`)可以包含其自身属性(比如本例中的`type`属性),也可以派生其原型对象中公有的属性。
|
原型对象`protoRabbit`是一个容器,用于包含所有兔子对象的公有属性。每个独立的兔子对象(比如`killerRabbit`)可以包含其自身属性(比如本例中的`type`属性),也可以派生其原型对象中公有的属性。
|
||||||
|
|
||||||
### 类
|
## 类
|
||||||
|
|
||||||
JavaScript 的原型系统可以解释为对一种面向对象的概念(称为类(class))的某种非正式实现。 类定义了对象的类型的形状 - 它具有什么方法和属性。 这样的对象被称为类的实例(instance)。
|
JavaScript 的原型系统可以解释为对一种面向对象的概念(称为类(class))的某种非正式实现。 类定义了对象的类型的形状 - 它具有什么方法和属性。 这样的对象被称为类的实例(instance)。
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ console.log(object.getWord());
|
|||||||
// → hello
|
// → hello
|
||||||
```
|
```
|
||||||
|
|
||||||
### 覆盖派生的属性
|
## 覆盖派生的属性
|
||||||
|
|
||||||
将属性添加到对象时,无论它是否存在于原型中,该属性都会添加到对象本身中。 如果原型中已经有一个同名的属性,该属性将不再影响对象,因为它现在隐藏在对象自己的属性后面。
|
将属性添加到对象时,无论它是否存在于原型中,该属性都会添加到对象本身中。 如果原型中已经有一个同名的属性,该属性将不再影响对象,因为它现在隐藏在对象自己的属性后面。
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ console.log(Object.prototype.toString.call([1, 2]));
|
|||||||
// → [object Array]
|
// → [object Array]
|
||||||
```
|
```
|
||||||
|
|
||||||
### 映射
|
## 映射
|
||||||
|
|
||||||
我们在上一章中看到了映射(map)这个词,用于一个操作,通过对元素应用函数来转换数据结构。 令人困惑的是,在编程时,同一个词也被用于相关而不同的事物。
|
我们在上一章中看到了映射(map)这个词,用于一个操作,通过对元素应用函数来转换数据结构。 令人困惑的是,在编程时,同一个词也被用于相关而不同的事物。
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ console.log({x: 1}.hasOwnProperty("toString"));
|
|||||||
// → false
|
// → false
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6.8 多态
|
## 多态
|
||||||
|
|
||||||
当你调用一个对象的`String`函数(将一个值转换为一个字符串)时,它会调用该对象的`toString`方法来尝试从它创建一个有意义的字符串。 我提到一些标准原型定义了自己的`toString`版本,因此它们可以创建一个包含比`"[object Object]"`有用信息更多的字符串。 你也可以自己实现。
|
当你调用一个对象的`String`函数(将一个值转换为一个字符串)时,它会调用该对象的`toString`方法来尝试从它创建一个有意义的字符串。 我提到一些标准原型定义了自己的`toString`版本,因此它们可以创建一个包含比`"[object Object]"`有用信息更多的字符串。 你也可以自己实现。
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ console.log(String(blackRabbit));
|
|||||||
|
|
||||||
我在第四章中提到`for/of`循环可以遍历几种数据结构。 这是多态性的另一种情况 - 这样的循环期望数据结构公开的特定接口,数组和字符串是这样。 你也可以将这个接口添加到你自己的对象中! 但在我们实现它之前,我们需要知道什么是符号。
|
我在第四章中提到`for/of`循环可以遍历几种数据结构。 这是多态性的另一种情况 - 这样的循环期望数据结构公开的特定接口,数组和字符串是这样。 你也可以将这个接口添加到你自己的对象中! 但在我们实现它之前,我们需要知道什么是符号。
|
||||||
|
|
||||||
### 符号
|
## 符号
|
||||||
|
|
||||||
多个接口可能为不同的事物使用相同的属性名称。 例如,我可以定义一个接口,其中`toString`方法应该将对象转换为一段纱线。 一个对象不可能同时满足这个接口和`toString`的标准用法。
|
多个接口可能为不同的事物使用相同的属性名称。 例如,我可以定义一个接口,其中`toString`方法应该将对象转换为一段纱线。 一个对象不可能同时满足这个接口和`toString`的标准用法。
|
||||||
|
|
||||||
@ -574,7 +574,7 @@ console.log(matrix.get(2, 3));
|
|||||||
|
|
||||||
尽管封装和多态可用于将代码彼此分离,从而减少整个程序的耦合,但继承从根本上将类连接在一起,从而产生更多的耦合。 继承一个类时,比起单纯使用它,你通常必须更加了解它如何工作。 继承可能是一个有用的工具,并且我现在在自己的程序中使用它,但它不应该成为你的第一个工具,你可能不应该积极寻找机会来构建类层次结构(类的家族树)。
|
尽管封装和多态可用于将代码彼此分离,从而减少整个程序的耦合,但继承从根本上将类连接在一起,从而产生更多的耦合。 继承一个类时,比起单纯使用它,你通常必须更加了解它如何工作。 继承可能是一个有用的工具,并且我现在在自己的程序中使用它,但它不应该成为你的第一个工具,你可能不应该积极寻找机会来构建类层次结构(类的家族树)。
|
||||||
|
|
||||||
### 6.12 `instanceof`运算符
|
## `instanceof`运算符
|
||||||
|
|
||||||
在有些时候,了解某个对象是否继承自某个特定类,也是十分有用的。JavaScript 为此提供了一个二元运算符,名为`instanceof`。
|
在有些时候,了解某个对象是否继承自某个特定类,也是十分有用的。JavaScript 为此提供了一个二元运算符,名为`instanceof`。
|
||||||
|
|
||||||
@ -592,7 +592,7 @@ console.log([1] instanceof Array);
|
|||||||
|
|
||||||
该运算符会浏览所有继承类型。所以`SymmetricMatrix`是`Matrix`的一个实例。 该运算符也可以应用于像`Array`这样的标准构造器。 几乎每个对象都是`Object`的一个实例。
|
该运算符会浏览所有继承类型。所以`SymmetricMatrix`是`Matrix`的一个实例。 该运算符也可以应用于像`Array`这样的标准构造器。 几乎每个对象都是`Object`的一个实例。
|
||||||
|
|
||||||
### 本章小结
|
## 本章小结
|
||||||
|
|
||||||
对象不仅仅持有它们自己的属性。对象中有另一个对象:原型,只要原型中包含了属性,那么根据原型构造出来的对象也就可以看成包含了相应的属性。简单对象直接以`Object.prototype`作为原型。
|
对象不仅仅持有它们自己的属性。对象中有另一个对象:原型,只要原型中包含了属性,那么根据原型构造出来的对象也就可以看成包含了相应的属性。简单对象直接以`Object.prototype`作为原型。
|
||||||
|
|
||||||
@ -608,9 +608,9 @@ console.log([1] instanceof Array);
|
|||||||
|
|
||||||
实现多个类,它们仅在一些细节上有所不同的时,将新类编写为现有类的子类,继承其一部分行为会很有帮助。
|
实现多个类,它们仅在一些细节上有所不同的时,将新类编写为现有类的子类,继承其一部分行为会很有帮助。
|
||||||
|
|
||||||
### 6.14 习题
|
## 习题
|
||||||
|
|
||||||
#### 6.14.1 向量类型
|
### 向量类型
|
||||||
|
|
||||||
编写一个构造器`Vec`,在二维空间中表示数组。该函数接受两个数字参数`x`和`y`,并将其保存到对象的同名属性中。
|
编写一个构造器`Vec`,在二维空间中表示数组。该函数接受两个数字参数`x`和`y`,并将其保存到对象的同名属性中。
|
||||||
|
|
||||||
@ -629,7 +629,7 @@ console.log(new Vec(3, 4).length);
|
|||||||
// → 5
|
// → 5
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 分组
|
### 分组
|
||||||
|
|
||||||
标准的 JavaScript 环境提供了另一个名为`Set`的数据结构。 像`Map`的实例一样,集合包含一组值。 与`Map`不同,它不会将其他值与这些值相关联 - 它只会跟踪哪些值是该集合的一部分。 一个值只能是一个集合的一部分 - 再次添加它没有任何作用。
|
标准的 JavaScript 环境提供了另一个名为`Set`的数据结构。 像`Map`的实例一样,集合包含一组值。 与`Map`不同,它不会将其他值与这些值相关联 - 它只会跟踪哪些值是该集合的一部分。 一个值只能是一个集合的一部分 - 再次添加它没有任何作用。
|
||||||
|
|
||||||
@ -656,7 +656,7 @@ console.log(group.has(10));
|
|||||||
// → false
|
// → false
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 可迭代分组
|
### 可迭代分组
|
||||||
|
|
||||||
使上一个练习中的`Group`类可迭代。 如果你不清楚接口的确切形式,请参阅本章前面迭代器接口的章节。
|
使上一个练习中的`Group`类可迭代。 如果你不清楚接口的确切形式,请参阅本章前面迭代器接口的章节。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user