Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions 1-js/01-getting-started/1-intro/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ JavaScript 在刚诞生的时候,它的名字叫 "LiveScript"。但是因为

不同的引擎有不同的“代号”,例如:

- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) —— Chrome 和 Opera 中的 JavaScript 引擎。
- [V8](https://en.wikipedia.org/wiki/V8_(JavaScript_engine)) —— Chrome、OperaEdge 中的 JavaScript 引擎。
- [SpiderMonkey](https://en.wikipedia.org/wiki/SpiderMonkey) —— Firefox 中的 JavaScript 引擎。
- ……还有其他一些代号,像 "Chakra" 用于 IE,"ChakraCore" 用于 Microsoft Edge,"Nitro" 和 "SquirrelFish" 用于 Safari,等等。
- ……还有其他一些代号,像 "Chakra" 用于 IE,"JavaScriptCore"、"Nitro" 和 "SquirrelFish" 用于 Safari,等等。

上面这些术语很容易记住,因为它们经常出现在开发者的文章中。我们也会用到这些术语。例如,如果“V8 支持某个功能”,那么我们可以认为这个功能大概能在 Chrome 和 Opera 中正常运行。
上面这些术语很容易记住,因为它们经常出现在开发者的文章中。我们也会用到这些术语。例如,如果“V8 支持某个功能”,那么我们可以认为这个功能大概能在 Chrome、OperaEdge 中正常运行。

```smart header="引擎是如何工作的?"

Expand Down Expand Up @@ -110,7 +110,8 @@ JavaScript 是将这三件事结合在一起的唯一的浏览器技术。
- [TypeScript](http://www.typescriptlang.org/) 专注于添加“严格的数据类型”以简化开发,以更好地支持复杂系统的开发。由微软开发。
- [Flow](http://flow.org/) 也添加了数据类型,但是以一种不同的方式。由 Facebook 开发。
- [Dart](https://www.dartlang.org/) 是一门独立的语言。它拥有自己的引擎,该引擎可以在非浏览器环境中运行(例如手机应用),它也可以被编译成 JavaScript。由 Google 开发。
- [Brython](https://brython.info/) 是一个 Python 的 JavaScript 编译器,可以在不使用 JavaScript 的情况下,以纯 Python 编写应用程序。
- [Brython](https://brython.info/) 是一个 Python 到 JavaScript 的转译器,让我们可以在不使用 JavaScript 的情况下,以纯 Python 编写应用程序。
- [Kotlin](https://kotlinlang.org/docs/reference/js-overview.html) 是一个现代、简洁且安全的编程语言,编写出的应用程序可以在浏览器和 Node 环境中运行。

这样的语言还有很多。当然,即使我们在使用此类编译语言,我们也需要了解 JavaScript。因为了解 JavaScript 才能让我们真正明白我们在做什么。

Expand Down
9 changes: 2 additions & 7 deletions 1-js/01-getting-started/2-manuals-specifications/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,11 @@

## 手册

- **MDN(Mozilla)JavaScript 索引** 是一个带有用例和其他信息的手册。它是一个获取关于个别语言函数、方法等深入信息的很好的来源
- **MDN(Mozilla)JavaScript 索引** 是一个带有用例和其他信息的主要的手册。它是一个获取关于个别语言函数、方法等深入信息的很好的信息来源

你可以在 <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference> 阅读它。

虽然,利用互联网搜索通常是最好的选择。只需在查询时输入“MDN [关键字]”,例如 <https://google.com/search?q=MDN+parseInt> 搜索 `parseInt` 函数。


- **MSDN** —— 一本微软的手册,它包含大量的信息,包括 JavaScript(在里面经常被写成 JScript)。如果有人需要关于 Internet Explorer 的规范细节,最好去看:<http://msdn.microsoft.com/>。

当然,我们还可以在使用互联网搜索中使用如 "RegExp MSDN" 或 "RegExp MSDN jscript" 这样的词条。
虽然,利用互联网搜索通常是最好的选择。只需在查询时输入“MDN [关键字]”,例如 <https://google.com/search?q=MDN+parseInt> 搜索 `parseInt` 函数。

## 兼容性表

Expand Down
1 change: 0 additions & 1 deletion 1-js/01-getting-started/3-code-editors/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ IDE 加载项目(通常包含很多文件),并且允许在不同文件之
下面是一些值得你关注的“轻量编辑器”:

- [Atom](https://atom.io/)(跨平台,免费)。
- [Visual Studio Code](https://code.visualstudio.com/)(跨平台,免费)。
- [Sublime Text](http://www.sublimetext.com)(跨平台,共享软件)。
- [Notepad++](https://notepad-plus-plus.org/)(Windows,免费)。
- [Vim](http://www.vim.org/) 和 [Emacs](https://www.gnu.org/software/emacs/) 也很棒,如果你知道怎么使用它们的话。
Expand Down
2 changes: 1 addition & 1 deletion 1-js/02-first-steps/01-hello-world/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

## “script” 标签

JavaScript 程序可以在 `<script>` 标签的帮助下插入到 HTML 文档的任何地方
我们几乎可以使用 `<script>` 标签将 JavaScript 程序插入到 HTML 文档的任何位置

比如:

Expand Down
33 changes: 15 additions & 18 deletions 1-js/02-first-steps/02-structure/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,39 +56,36 @@ alert(3 +
如果你好奇地想知道一个这种错误的具体例子,那你可以看看下面这段代码:

```js run
[1, 2].forEach(alert)
alert("Hello");

[1, 2].forEach(alert);
```

你不需要考虑方括号 `[]` 和 `forEach` 的含义,现在它们并不重要,之后我们会学习它们。让我们先记住这段代码的运行结果:先显示 `1`,然后显示 `2`。
你不需要考虑方括号 `[]` 和 `forEach` 的含义,现在它们并不重要,之后我们会学习它们。让我们先记住这段代码的运行结果:先显示 `Hello`,然后显示 `1`,然后 `2`。

现在我们在代码前面插入一个 `alert` 语句,并且不加分号
现在,让我们删除 `alert` 语句后的分号

```js run no-beautify
alert("There will be an error")
alert("Hello")

[1, 2].forEach(alert)
[1, 2].forEach(alert);
```

现在,如果我们运行代码,只有第一个 `alert` 语句的内容被显示了出来,随后我们收到了一个错误!

但是,如果我们在第一个 `alert` 语句末尾加上一个分号,就工作正常了:
```js run
alert("All fine now");

[1, 2].forEach(alert)
```
与上面的代码相比只有一个字符的区别:第一行末尾的分号不见了。

现在,我们能得到 "All fine now",然后是 `1` 和 `2`
如果我们运行这段代码,只有第一个 `Hello` 会被显示出来(并且有一个报错,你可能需要打开控制台才能看到它)。并且不会再有数字被显示出来

无分号的变体(variant)会出现报错,是因为 JavaScript 并不会在方括号 `[...]` 前添加一个隐式的分号
这是因为,JavaScript 引擎并没有假设在方括号 `[...]` 前有一个分号。因此,最后一个示例中的代码被视为了单个语句

所以,因为没有自动插入分号,第一个例子中的代码被视为了一条简单的语句,我们从引擎看到的是这样的
对于引擎来说,它是这样的

```js run no-beautify
alert("There will be an error")[1, 2].forEach(alert)
alert("Hello")[1, 2].forEach(alert);
```

但它应该是两条语句,而不是一条。这种情况下的合并是不对的,所以才会造成错误。诸如此类,还有很多。
看起来很奇怪,对吧?在这种情况下,这样将两行代码合并到一起是不对的。我们需要在 `alert` 后面加一个分号,代码才能正常运行。

这也可能发生在其他情况下。
````

即使语句被换行符分隔了,我们依然建议在它们之间加分号。这个规则被社区广泛采用。我们再次强调一下 —— 大部分时候可以省略分号,但是最好不要省略分号,尤其对新手来说。
Expand Down
2 changes: 1 addition & 1 deletion 1-js/02-first-steps/04-variables/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let message;
let message;

*!*
message = 'Hello'; // 保存字符串
message = 'Hello'; // 将字符串 'Hello' 保存在名为 message 的变量中
*/!*
```

Expand Down
2 changes: 1 addition & 1 deletion 1-js/02-first-steps/05-types/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ n = 12.345;

我们将在 <info:number> 一节中学习数字的更多细节。

## BigInt 类型
## BigInt 类型 [#bigint-type]

在 JavaScript 中,"number" 类型无法表示大于 <code>(2<sup>53</sup>-1)</code>(即 `9007199254740991`),或小于 <code>-(2<sup>53</sup>-1)</code> 的整数。这是其内部表示形式导致的技术限制。

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ true + false = 1
"$" + 4 + 5 = "$45"
"4" - 2 = 2
"4px" - 2 = NaN
7 / 0 = Infinity
" -9 " + 5 = " -9 5" // (3)
" -9 " - 5 = -14 // (4)
null + 1 = 1 // (5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ true + false
"$" + 4 + 5
"4" - 2
"4px" - 2
7 / 0
" -9 " + 5
" -9 " - 5
null + 1
Expand Down
24 changes: 17 additions & 7 deletions 1-js/02-first-steps/08-operators/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,21 @@ alert( 8 % 3 ); // 2,8 除以 3 的余数

### 求幂 **

求幂运算 `a ** b` 是 `a` 乘以自身 `b` 次。
求幂运算 `a ** b` 将 `a` 提升至 `a` 的 `b` 次幂。

在数学中我们将其表示为 a<sup>b</sup>。

例如:

```js run
alert( 2 ** 2 ); // 4 (2 * 2,自乘 2 次)
alert( 2 ** 3 ); // 8 (2 * 2 * 2,自乘 3 次)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2,自乘 4 次)
alert( 2 ** 2 ); // 2² = 4
alert( 2 ** 3 ); // 2³ = 8
alert( 2 ** 4 ); // 2⁴ = 16
```

在数学上,求幂的定义也适用于非整数。例如,平方根是以 `1/2` 为单位的求幂:
就像在数学计算中一样,幂运算也适用于非整数。

例如,平方根是指数为 ½ 的幂运算:

```js run
alert( 4 ** (1/2) ); // 2(1/2 次方与平方根相同)
Expand Down Expand Up @@ -104,7 +108,13 @@ alert( 2 + '1' ); // "21"
alert(2 + 2 + '1' ); // "41",不是 "221"
```

在这里,运算符是按顺序工作。第一个 `+` 将两个数字相加,所以返回 `4`,然后下一个 `+` 将字符串 `1` 加入其中,所以就是 `4 + '1' = 41`。
在这里,运算符是按顺序工作。第一个 `+` 将两个数字相加,所以返回 `4`,然后下一个 `+` 将字符串 `1` 加入其中,所以就是 `4 + '1' = '41'`。

```js run
alert('1' + 2 + 2); // "122",不是 "14"
```

这里,第一个操作数是一个字符串,所以编译器将其他两个操作数也视为了字符串。`2` 被与 `'1'` 连接到了一起,也就是像 `'1' + 2 = "12"` 然后 `"12" + 2 = "122"` 这样。

二元 `+` 是唯一一个以这种方式支持字符串的运算符。其他算术运算符只对数字起作用,并且总是将其运算元转换为数字。

Expand Down Expand Up @@ -214,7 +224,7 @@ alert( x ); // 5

`=` 是一个运算符,而不是一个有着“魔法”作用的语言结构。

在 JavaScript 中,大多数运算符都会返回一个值。这对于 `+` 和 `-` 来说是显而易见的,但对于 `=` 来说也是如此。
在 JavaScript 中,所有运算符都会返回一个值。这对于 `+` 和 `-` 来说是显而易见的,但对于 `=` 来说也是如此。

语句 `x = value` 将值 `value` 写入 `x` **然后返回 x**。

Expand Down
2 changes: 1 addition & 1 deletion 1-js/02-first-steps/09-comparison/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- 大于 / 小于:<code>a &gt; b</code>,<code>a &lt; b</code>。
- 大于等于 / 小于等于:<code>a &gt;= b</code>,<code>a &lt;= b</code>。
- 检查两个值的相等:`a == b`,请注意双等号 `==` 表示相等性检查,而单等号 `a = b` 表示赋值。
- 检查两个值不相等不相等在数学中的符号是 <code>&ne;</code>,但在 JavaScript 中写成 <code>a != b</code>。
- 检查两个值不相等不相等在数学中的符号是 <code>&ne;</code>,但在 JavaScript 中写成 <code>a != b</code>。

在本文中,我们将进一步了解不同类型的比较,JavaScript 是如何进行比较的,包括一些重要的特殊性。

Expand Down
5 changes: 2 additions & 3 deletions 1-js/02-first-steps/10-ifelse/2-check-standard/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ importance: 2

# JavaScript 的名字

使用 `if..else` 结构,实现提问 "What is the "official" name of JavaScript?" 的代码
使用 `if..else` 结构,实现提问 JavaScript 的“官方”名称是什么?”的代码

如果访问者输入了 "ECMAScript",输出就提示 "Right!",否则 — 输出:"Didn't know? ECMAScript!"
如果访问者输入了 "ECMAScript",输出就提示 "Right!",否则 — 输出:“你不知道?ECMAScript!”

![](ifelse_task2.svg)

[demo src="ifelse_task2"]

4 changes: 2 additions & 2 deletions 1-js/02-first-steps/11-logical-operators/article.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 逻辑运算符

JavaScript 中有三个逻辑运算符:`||`(或),`&&`(与),`!`(非)。
JavaScript 中有四个逻辑运算符:`||`(或),`&&`(与),`!`(非),`??`(空值合并运算符)。本文我们先介绍前三个,在下一篇文章中再详细介绍 `??` 运算符

虽然它们被称为“逻辑”运算符,但这些运算符却可以被应用于任意类型的值,而不仅仅是布尔值。它们的结果也同样可以是任意类型。

Expand Down Expand Up @@ -64,7 +64,7 @@ if (hour < 10 || hour > 18 || isWeekend) {
}
```

## 或运算寻找第一个真值
## 或运算寻找第一个真值 [#or-finds-the-first-truthy-value]

上文提到的逻辑处理多少有些传统了。下面让我们看看 JavaScript 的“附加”特性。

Expand Down
29 changes: 16 additions & 13 deletions 1-js/02-first-steps/12-nullish-coalescing-operator/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@

[recent browser="new"]

在本文中,我们将值既不是 `null` 也不是 `undefined` 的表达式称为“已定义的(defined)”。

空值合并运算符(nullish coalescing operator)的写法为两个问号 `??`。

由于它对待 `null` 和 `undefined` 的方式类似,所以在本文中我们将使用一个特殊的术语对其进行表示。我们将值既不是 `null` 也不是 `undefined` 的表达式称为“已定义的(defined)”。

`a ?? b` 的结果是:
- 如果 `a` 是已定义的,则结果为 `a`,
- 如果 `a` 不是已定义的,则结果为 `b`。


换句话说,如果第一个参数不是 `null/undefined`,则 `??` 返回第一个参数。否则,返回第二个参数。

空值合并运算符并不是什么全新的东西。它只是一种获得两者中的第一个“已定义的”值的不错的语法。
Expand All @@ -21,22 +20,24 @@
result = (a !== null && a !== undefined) ? a : b;
```

现在你应该清楚了 `??` 的作用。让我们来看看它的使用场景吧。

通常 `??` 的使用场景是,为可能是未定义的变量提供一个默认值。

例如,在这里,如果 `user` 是未定义的,我们则显示 `Anonymous`:
例如,在这里,如果 `user` 是已定义的则显示 `user`,否则显示 `匿名`:

```js run
let user;

alert(user ?? "Anonymous"); // Anonymous
alert(user ?? "匿名"); // 匿名(user 未定义)
```

当然,如果 `user` 的值为除 `null/undefined` 外的任意值,那么我们看到的将是它
在下面这个例子中,我们将一个名字赋值给了 `user`:

```js run
let user = "John";

alert(user ?? "Anonymous"); // John
alert(user ?? "匿名"); // John(user 已定义)
```

我们还可以使用 `??` 序列从一系列的值中选择出第一个非 `null/undefined` 的值。
Expand Down Expand Up @@ -75,7 +76,7 @@ alert(firstName || lastName || nickName || "Anonymous"); // Supercoder
*/!*
```

或 `||` 运算符自 JavaScript 诞生就存在,因此开发者长期将其用于这种目的。
纵观 JavaScript 发展史,或 `||` 运算符先于 `??` 出现。它自 JavaScript 诞生就存在了,因此开发者长期将其用于这种目的。

另一方面,空值合并运算符 `??` 是最近才被添加到 JavaScript 中的,它的出现是因为人们对 `||` 不太满意。

Expand All @@ -96,16 +97,18 @@ alert(height || 100); // 100
alert(height ?? 100); // 0
```

- `height || 100` 首先会检查 `height` 是否为一个假值,发现它确实是
- 所以,结果为第二个参数,`100`。
- `height || 100` 首先会检查 `height` 是否为一个假值,它是 `0`,确实是假值
- 所以,`||` 运算的结果为第二个参数,`100`。
- `height ?? 100` 首先会检查 `height` 是否为 `null/undefined`,发现它不是。
- 所以,结果为 `height` 的原始值,`0`。

如果高度 `0` 为有效值,则不应将其替换为默认值,所以 `??` 能够得出正确的结果
实际上,高度 `0` 通常是一个有效值,它不应该被替换为默认值。所以 `??` 运算得到的是正确的结果

## 优先级

`??` 运算符的优先级相当低:在 [MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table) 中为 `5`。因此,`??` 在 `=` 和 `?` 之前计算,但在大多数其他运算符(例如,`+` 和 `*`)之后计算。
`??` 运算符的优先级与 `||` 差不多,只是稍微低一点。`??` 运算符的优先级为 `5`,`||` 为 `6` ,详见:[MDN table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Table) 。

这意味着,就像 `||` 一样,空值合并运算符在 `=` 和 `?` 运算前计算,但在大多数其他运算(例如 `+` 和 `*`)之后计算。

因此,如果我们需要在还有其他运算符的表达式中使用 `??` 进行取值,需要考虑加括号:

Expand Down Expand Up @@ -139,7 +142,7 @@ let area = height ?? (100 * width) ?? 50;
let x = 1 && 2 ?? 3; // Syntax error
```

这个限制无疑是值得商榷的,但它被添加到语言规范中是为了避免人们从 `||` 切换到 `??` 时的编程错误。
这个限制无疑是值得商榷的,它被添加到语言规范中是为了避免人们从 `||` 切换到 `??` 时的编程错误。

可以明确地使用括号来解决这个问题:

Expand Down
17 changes: 14 additions & 3 deletions 1-js/02-first-steps/13-while-for/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ for (let i = 0; i < 3; i++) { // 结果为 0、1、2

| 语句段 | | |
| ----- | ----------- |----------------------------------------------------------------------------|
| begin | `i = 0` | 进入循环时执行一次。 |
| begin | `let i = 0` | 进入循环时执行一次。 |
| condition | `i < 3` | 在每次循环迭代之前检查,如果为 false,停止循环。 |
| body(循环体) | `alert(i)` | 条件为真时,重复运行。 |
| step | `i++` | 在每次循环体迭代后执行。 |
Expand Down Expand Up @@ -363,12 +363,23 @@ for (let i = 0; i < 3; i++) { ... }

例如,这样做是不可能的:
```js
break label; // 无法跳转到这个标签
break label; // 跳转至下面的 label 处(无效)

label: for (...)
```

只有在循环内部才能调用 `break/continue`,并且标签必须位于指令上方的某个位置。
`break` 指令必须在代码块内。从技术上讲,任何被标记的代码块都有效,例如:
```js
label: {
// ...
break label; // 有效
// ...
}
```

……尽管 99.9% 的情况下 `break` 都被用在循环内,就像在上面那些例子中我们看到的那样。

`continue` 只有在循环内部才可行。
````

## 总结
Expand Down
2 changes: 1 addition & 1 deletion 1-js/02-first-steps/14-switch/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ switch (a) {
break;
*/!*
case 5:
alert( 'Too large' );
alert( 'Too big' );
break;
default:
alert( "I don't know such values" );
Expand Down
Loading