本系列文章是《JavaScript 权威指南》第七版的读书笔记, 《JavaScript 权威指南》的作者是 David Flanagan,该书是 JavaScript 的经典书籍,被大家称为 犀牛书
。该书的目标是全面、权威地讲解 JavaScript 语言,对 JavaScript 程序中可能用到的最重要的客户端 API 和服务器端 API 提供深入的介绍。
JavaScript 简介
JavaScript 是 Web 编程语言。绝大多数网站都使用 JavaScript,所有现代 Web 浏览器都包含 JavaScript 解释器,这让 JavaScript 成为有史以来部署最广泛的编程语言。而 Node.js 让浏览器之外的 JavaScript 编程成为可能,Node 的巨大成功意味着 JavaScript 如今也是软件开发者最常用的编程语言。
JavaScript 是一门高级、动态、解释型编程语言,非常适合面向对象和函数式编程风格。JavaScript 这个名字相当有误导性,其实它和 Java 没有任何关系。
JavaScript 是 Netscape 在 Web 诞生初期创造的,之后它将该语言提交给 ECMA 组织进行标准化。由于商标的问题,这门语言的标准版本使用 ECMAScript
这个名字。实践中大家仍称这门语言为 JavaScript。一般在讨论这门语言的标准及版本时使用 ECMAScript
或其缩写 ES
。
- 2010 年以来,几乎所有浏览器都支持 ECMAScript 5 标准
- ES6 发布于 2015 年,增加了重要的新特性。这些新特性把 JavaScript 从一门脚本语言转变为一门适合大规模软件工程的严肃、通用语言
- 从 ES6 开始,ECMAScript 规范每年发布一次,语言的版本也以发布的年份来标识(例如 ES2016、ES2017 等)
JavaScript 发展过程中,也会纠正早期版本的缺陷,但是由于兼容性,某个特性即使问题严重,也不能将其删除。ES5 及其之后,可以选择切换到 JavaScript 严格模式
,在这种模式下,某些早期的语法错误会得到纠正。在 ES6 及之后,使用新语言特性经常会隐式触发严格模式。在这些上下文中,不能使用老旧、有缺陷的特性。
核心 JavaScript 语言定义了最小限度的 API,可以操作数值、文本、数组、集合、映射等,但不包含任何输入和输出功能。输入和输出(以及更复杂的特性,如联网、存储和图形处理)是内嵌 JavaScript 的 宿主环境
的责任。
- 浏览器是 JavaScript 最早的宿主环境,也是 JavaScript 最常见的运行环境。浏览器环境允许 JavaScript 代码从用户的鼠标和键盘或者通过发送 HTTP 请求获取输入,也允许 JavaScript 代码通过 HTML 和 CSS 向用户显示输出
- 2010 年之后,Node 的出现让 JavaScript 有了一种新的宿主环境。与限制 JavaScript 只能使用浏览器提供的 API 不同,Node 给与 JavaScript 完整的操作系统访问权限,这使得 JavaScript 程序可以读写文件、通过网络传送数据、处理 HTTP 请求等
探索 JavaScript
如果只是想要尝试少量 JavaScript 代码,可以打开浏览器的开发者工具,然后选择 Console
标签页,之后就可以在提示符后面输入代码。另外一种方式是下载并安装 Node,安装 Node 之后,直接输入 node 命令,既可以开始交互式的 JavaScript 会话。
1 | # node |
Hello, World
当要编写更长的代码时,这种以行为单位的交互环境就不合适了。此时就需要使用文本编辑器(或者 IDE)来编写 JavaScript 代码,然后将其保存到文件中(JavaScript 代码文件通常以 .js
扩展名结尾),再使用 Node 来运行这个 JavaScript 代码文件。
例如,创建一个名为 hello.js
的文件,内容如下:
1 | // console 在终端窗口或者浏览器开发者工具的控制台中输出信息 |
接下来使用 node 来执行该文件:
1 | # node hello.js |
如果想要在浏览器中运行该脚本文件,则需要通过 html 文件来引入该 js 文件:
1 | <script src="hello.js"></script> |
在浏览器中打开该 html 文件,就可以在浏览器开发者工具的控制台中看到 Hello World!
。
JavaScript 之旅
如下是一个更复杂的示例:
1 | // define variable |
- JavaScript 以
//
开始注释内容,//
后面的文字都是注释内容 - 变量使用 let 关键字声明,变量是一个代表值的名字
- 使用 = 为变量赋值
- JavaScript 支持数值(整数或实数)、字符串(双引号或单引号所引用的字符序列)、布尔值、null(特殊值,意思为没有值)、undefined(特殊值,表示变量已被声明但未初始化)
- JavaScript 支持对象,对象是一个
名/值
对的集合,或者一个字符串到值的映射。支持?.
条件式访问属性 - JavaScript 支持数组(以数值作为索引的列表)
- 在
中括号中罗列出数组元素
以及在大括号中将对象属性名映射为属性值
的语法被称为初始化表达式
表达式在 JavaScript 中就是一个短语,可以求值产生一个值。JavaScript 构造表达式最常见的方式是使用操作符。变量名也是表达式。表达式只用于计算值,什么也不做,即不以任何方式改变程序的状态。
JavaScript 语句则像一个完整的句子,语句没有值,但是却会改变状态,例如变量声明语句和赋值语句。
函数是一个有名字、有参数的 JavaScript 代码块,只要定义一次就可以反复调用。函数也是值,可以赋给变量。如下是一个示例:
1 | function plus1(x) { |
ES6 及之后,有一种定义函数的简写方式。这种简洁的语法使用 =>
来分隔参数列表和函数体,因此以这种方式定义的函数被称为箭头函数。箭头函数常用于把一个未命名的函数作为参数传递给另一个函数:
1 | const plus1 = x => x + 1; |
在通过对象使用函数时,我们称其为方法。所有的 JavaScript 对象(包括数组)都可以有方法,我们可以将函数赋值给对象的属性,从而为对象添加方法。此时 this 关键字引用的是方法所在的对象:
1 | let a = []; |
接下的实例则演示了 JavaScript 中常用的控制结构:
1 | function abs(x) { |
JavaScript 支持面向对象的编程风格,但与 经典的
面向对象编程语言非常不一样。如下是一个简单的示例:
1 | class Point { |
- 按照惯例,类名需要首字母大写
- 构造函数用于初始化新实例,this 代表要初始化的对象,构造函数不需要 return 语句
字符频率柱形图
如下是一个更复杂的 JavaScript 程序,使用了一些 JavaScript 高级特性,通过这个程序可以感受真正的 JavaScript 长什么样:
1 | class DefaultMap extends Map { |
该程序可以统计所输入zi符串中每个字符的频率,并以柱形图的形式展示:
1 | # node diagram.js |