手记

JavaScript 从 0 到 1 入门手册(一)

前言

在学习 JavaScript 的过程中,我们通常会把 JavaScript 分为以下三个部分

  1. JavaScript核心语言(The Core (ECMAScript))
  2. 文档对象模型(The Document Object Model (DOM))
  3. 浏览器对象模型(The Browser Object Model (BOM))

本手册将把重点放到 JavaScript 语言本身身上,也就是第一部分 JavaScript 核心语言(The Core (ECMAScript)

如果你把 JavaScript 选为你的第一门语言,那么希望本手册能够帮助到你尽快掌握它,而如果你已经在日常开发中使用 JavaScript 了,那么本手册的内容也是一个很好的复习。

我们将包含如下知识点:

  1. 了解历史
  2. 语法概述
  3. 值和类型
  4. 变量
  5. 类型
  6. 表达式
  7. 运算符
  8. 条件语句
  9. 数组
  10. 字符串
  11. 循环
  12. 函数与函数表达式
  13. 箭头函数
  14. 对象
  15. 继承
  16. 异步编程和回调
  17. Promises
  18. Async and Await
  19. Variable scope
  20. 总结以及下一步

了解历史

在正式开始学习前,我们先来简短地看一下 JavaScript 的历史,这有助于第一次接触 JavaScript 的人更好地学习。

诞生

JavaScript 创建于 1995 年。由当时 Netscape (网景) 公司的 Brendan Eich (布兰登·艾克) 负责开发,最初命名为 Mocha,后来改名为 LiveScript,最后才重命名为 JavaScript

在创建的初期,JavaScript 并没有对应的标准(没有统一的语法或功能),这造成了浏览器脚本编写的困难,所以当时业界都希望可以把 JavaScript 语言标准化

标准化

1997 年,JavaScript 1.1 版本被提交到了 ECMA(欧洲计算机制造商协会)ECMA 把它分配给了 TC39 技术委员会,希望可以制定出一个标准、通用、跨平台且和各大浏览器厂商都无关的标准。

TC39 技术委员会在当时包括了 NetscapeSunMicrosoftBorland 等占据市场主流的技术公司,几个月的技术会议后,最终发布了 ECMA-262

ECMA-262 这份标准定义了一种新的脚本语言,名称就是我们现在听到的 ECMAScript,至于为什么叫 ECMAScript 而不是就叫 JavaScript,这有可能是因为当时一些相关的法律或者品牌的原因所造成的。

版本名称的变化

JavaScript 其实是 ECMAScript 标准的实现,这就是为什么您会听到有关 ES6ES2015ES2016ES2017ES2018ES2019ES2020 等的原因,ES 指的就是 ECMAScript

如果你看到我上面罗列的一些版本名称,你会奇怪有一个 ES6,而其他都是 ES + 年份,这其实是因为这个更改的时间有点晚。

当时 ES5 是 2009 年时发布 ECMAScript 规范的名称,这导致 ES5 的下一个版本被人们称为 ES6,而且官方决定宣布使用 ES2015 而不是 ES6 的时间点其实很晚,这也就导致了目前在社区会有 ES6ES7ES8ES9ES10 这些版本名称的出现,但是其实 ES + 年份才是目前的官方名称。

其他

除了 JavaScript 外,其实也有其他语言也实现了 ECMAScript,比如 ActionScript,它是 Flash 的脚本语言,但是目前已经逐渐消失了。

现在,支持 ECMAScript 规范的语言就是 JavaScript

其中,ES5 从 2009 年到现在,已经过去超过 10 年,虽然 ES5 在 JavaScript 的历史中是一个非常重要的版本,但是 ES5 的很多知识已经不值得再投入过多时间。

现在,我们应该转向 ES2015(ES6) 或之后的版本进行学习。

语法概述

大小写

JavaScript 是区分大小写的,不管是变量、函数名还是运算符都区分大小写,比如变量名 Apple 和 apple 就代表了两个变量。

标识符的合法性

我们上面提到的变量 apple,其实就是程序中的标识符

标识符是用于描述程序中变量函数属性参数等的名称。

在 JavaScript 中,一个合法的标识符规则如下:

  • 第一个字符必须是字母下划线( _ )美元符号( $ )
  • 其他所有字符可以是字母下划线( _ )美元符号( $ )数字
  • 不能是 JavaScript 中的关键字保留字

另外,对于标识符,有三点需要提到:

  1. 标识符如果包含 两个或两个以上 的单词时,那么应该采用 驼峰式 的写法,第一个单词的首字母小写,后面的单词首字母大写,比如 myApple。
  2. 美元符号通常在引用 DOM 元素时被使用,又或者被一些常用的库所使用(比如 jQuery),所以平时我们命名变量也很少使用美元符号( $ )
  3. 我们很少会去背关键字保留字,一般都是学习中或使用中慢慢熟悉。

注释

JavaScript 采用 C语言 风格的注释,即使用 //单行注释,和使用 /* */多行注释

如:

// 单行注释

/*
多
行注释
*/

分号

分号(;) 用于结束一条语句,而一些足够聪明的解释器可以识别一条语句什么时候结束。

这就导致了目前的一个争议,一些开发人员建议始终使用分号,而另一些开发人员认为不需要使用分号

这里的重点是,保持统一的做法

如果使用分号就都使用,不要在一个项目中,一个地方使用分号,另一个地方不使用。

以下两条语句的区别只在于代码风格的不同:

const hello = 1;
let world = 2

风格可以讨论,但不需要一个定论。

值和类型

JavaScript 有很多种类型,但是目前还没到展开的时候,我们现在需要了解的是每一个都有对应的类型

比如 100 是一个,而数字是这个类型。又比如 apple 是一个,而字符串是这个类型

通常,我们会说,字符串 apple,数字 100。

而当我们需要使用这些的时候,我们需要把它们存储到变量中,而每个变量都有一个变量名(也就是标识符)来标识它,这样我们就可以通过变量名来找到我们要使用的了。

变量

首先,变量是什么?

对于初学者来说,一个易于理解的例子就是,变量是程序中的一个盒子,并且盒子上贴有唯一的标签(变量名),而盒子里面的内容,就是我们的

另外,可以想象盒子的大小或者形状则是我们的类型

我们将使用两个关键字去声明变量,一个是 const(常量),另一个是 let(变量)

const foo = 1
let bar = 2

const

const(常量) 声明了该变量不能为这个变量重新分配一个值了。

例如,以下操作将会报错:

const foo = 1
foo = 2

JavaScript中的常量和一些编程语言中的常量是有区别的。

对于 const,我们并没有说不能改变它的值,而是说不能为这个变量重新赋值。

那么,如果我们使用 const 声明一个对象,其实是可以修改这个对象的属性的。

这一点,我们将在学习对象中讨论。

常量的命名

现实中,对于常量的命名,我们有一个常规做法就是都大写,比如上面的例子,我们将命名为 FOO

但是也有另外一种情况,就是我们的常量的值并非是提前知道的,而是需要在执行期间才能获得,那么,此时的常量的命名仍然使用驼峰式

以下 const 变量名命名的例子:

const APPLE_COLOR_RED = "#F00"
const codeExcuTime = /* 值将来自代码执行后 */

let

let 声明的变量可以重新分配一个值。
例如,以下操作将会成功:

let bar = 2
bar = 3

var

var 是 ES6 之前用于声明变量关键字

下面是一个例子

var foo = 2

var 类似我们的 let,这里不会进入过多的讨论,现实中,我们应该避免使用 var

建议

总的来说,我们通过声明变量来存放我们的数据。

对于现在,我们应该只使用两个关键字来声明变量,letconst

其中的不同是,如果是使用 const 声明变量,那就表示我们不希望这个变量的值被再次赋值。

注意,JavaScript 中,const 虽然表示常量,但并没有表示不能修改它的值。

我们也提到的另外一个关键字 var,但我认为应该在你需要的时候再花时间去了解它。

项目中,我们应该避免使用 var,更多考虑使用的是 const,然后才是 let

类型

从一般的编程概念来看,变量的类型定义了可以存放到这个变量中的,以及可以对这个值所进行的操作

比如一个变量存放的值是数字类型,那么这个变量可以执行加减乘除操作。

通常,我们会把类型划分为两类:

  • Primitive Types(原始类型)
  • Object Types (对象类型)

原始类型

JavaScript 中,原始类型包括了 NumberBigIntStringBooleanSymbol

另外,我们把 NullUndefined 这两个特殊的类型也划分到原始类型中,所以总共有 7原始类型

对象类型

对象类型,也就是 Object 类型

可以说 JavaScript 中,除去原始类型就是对象类型了。
对象类型涉及到 properties(属性)methods(方法),我们将会在对象的知识点中讨论。

在各大经典的 JavaScript 教程中都使用了原始类型对象类型来对 JavaScript 中的类型进行划分。

但是在规范(ECAMScript2020)中并没有这种划分。只是直接列出了 8 种类型,也就是我们提到的 UndefinedNullBooleanStringSymbolNumberBigIntObject

其中 SymbolBigInt 算是后加进来的,所以在一些旧的教程中,你可能看到的是 6 种,而不是 8 种。

表达式

表达式总是和语句产生关联,这也在社区中造成了一些争议,但从掌握一门编程语言的过程来看,我认为区分表达式语句还是有必要的,这对我们学习和理解函数式编程也有帮助。

表达式和语句的区别

语句其实是由关键字组成的一条命令,用于告诉 JavaScript 做什么,比如我们常会说的导入某某库,这就需要我们写语句来告诉 JavaScript了。

以下是一个语句的另外一个例子,用于告诉 JavaScript,我们声明了一个变量,并把一个值存储到该变量中:

let foo = 101

表达式可以看做就是值,以下就是一些表达式

101
1.38
'apple'
true
false

我们可以看到,表达式其实是表达一个,这就导致了表达式通常被放到等号的右边。

语句通常都会涉及到关键字,比如循环语句,用于告诉 JavaScript 这里需要重复执行。

在我们后面接触的语句越来越多的时候,就可以更好地理解了。

表达式的分类

通过表达式,我们会得到一个,这里如果细分,又可以分为算术表达式,这将得到一个数字,比如:

1 + 2
i++
i * 100

又或者字符串表达式逻辑表达式,比如:

// 结果是 hello world!
’hello' + ' ' + 'world!'
// 结果是 true 或者 false
isCar && isHouse

除此之外,还可以是我们后面学到的函数对象数组等,后面的章节将会介绍它们。

运算符

运算符的其实是 Operator 的翻译。

前面我们提到,类型定义了可以对值所进行的操作

所以,通常的翻译是操作符,而运算符,我觉得更多是数学上的概念,可能会更通俗一些。

但某些操作使用操作符可能会更好理解,所以,有时候也会使用操作符

赋值运算符

我们已经见过不少运算符了,第一个要正式介绍的运算符我们也已经见过,就是等号( = )

等号其实是赋值运算符,用于分配

另一种说法是初始化

以下就是一个初始化变量的例子:

// 把 score 初始化为 100
let score = 100

算术运算符

最常见的算术运算符当然就是 加( + )减( - )乘( * )除( / ) 了。

除此之外,还有取余(%)求幂()** 。

以下是 例子:

let foo = 1 + 2
foo = 1 - 2
foo = 1 * 2
foo = 1 / 2
foo = 2 % 3
foo = 1 ** 2

Infinity 和 NaN

InfinityNaN 其实 JavaScript 全局对象中的属性属性的值就是他们本身。

我们还没有聊得到对象,但是这里由于算术表达式会导致这两个值出现,所以我们有必要了解一下。

Infinity

除法中,如果除以零,JavaScript 给出的结果是Infinity(正无穷大),或者是 -Infinity(负无穷大),而不是报错。

let foo = 1 / 0 // Infinity
foo = -1 / 0 // -Infinity

另外,Infinity 和数学中的无穷大概念很类似,比如任何正数乘以 Infinity 会得到 正Infinity(负数则得负 Infinity,任何正数值除以 Infinity,则得到正 0。

NaN

NaN(Not-A-Number) 表示不是一个数字。

我们都知道 0 不能做除数,那么如果这么做,JavaScript 会告诉你得到的不是一个数字,也就是 NaN

如下是一个例子:

let foo = 1 % 0 // NaN
foo = -1 % 0 // NaN

通常 NaN 的出现,其实就和它的含义一样,通过计算,得到了一个不能表示为数字的值。

比如操作符中两个变量的类型不同,又或者其中一个变量的值已经为 NaN 了.
如:

'a' / 1 // NaN
1 + ('a' / 1) // NaN

对于运算中何时会出现 Infinity,何时会出现 NaN,在 ECMA 的规范中罗列了很多情况,刚开始学习的时候我们并没有必要每一条都找出来,只需要知道这两个值得含义就好了。

下图是 ECMA2020 中关于仅关于除法操作出现的情况,大家感受一下:

运算符的优先级

我们都知道在数学中,加减乘除运算是有优先级的,通常口诀就是先乘除,后加减

在 JavaScript 中也是一样的,运算符优先级决定了运算执行的先后顺序

比如:

1 + 2 * 3 // 1 + 6 结果为 7

所有操作符都有优先级,有人汇总成了一个表格,但是我们并不需要去背这个。

因为我们有一个处理优先级的超强办法,就是使用小括号(或者说是圆括号)

下面是一个例子:

(1 + 2) * 3 // 3 * 3 结果为 9

小括号优先级最高的,并且本身没有关联性

关联性指的是,如果大家的优先级相同,那么我们应该怎么执行。

一般来说,关联性分为左关联(从左到右执行)右关联(从右到左执行)

比如我们的加减乘除就是左关联的,那么 1 + 2 + 3,会优先考虑计算 1 加 2,然后再加 3 了。

右关联的一个例子就是我们的赋值操作符

在一条赋值语句中,JavaScript 会把等号右边的表达式算出来后再赋值给等号左边的变量中:

let foo = 1 + 2 * 3 // 把7算出来后,再存储到 foo 变量中

比较运算符

第三个要了解的运算符是比较运算符

比较过后,我们会得到一个布尔类型的值,总共就两个,分别是 truefalse

常见的比较运算符如下:

  • < (小于)
  • <= (小于或等于)
  • >(大于)
  • >=(大于或等于)
  • === (是否相等)
  • !== (是否不相等)

下面是例子:

let foo = 1
foo >= 1 // true

关于相等不相等,其实还有另外的运算符,==!=。对于初学者来说,我们应该选择使用 === 来进行检查是否相等,使用 !== 来检查是否不相等

这也是现实编程中的常规选择。

有了比较运算符之后,我们就可以讨论开始条件语句了,我们将在 JavaScript 从 0 到 1 入门手册(2020版)(二) 中开始讨论接下来的内容。

3人推荐
随时随地看视频
慕课网APP