JavaScript-高级程序设计-Notes
第1章 什么是 JavaScript
1.2 JavaScript 实现
JavaScript 和 ECMAScript 基本上是同义词.
包括的部分:
1.2.1 ECMAScript
ECMAScript 是 ECMA-262 定义的语言,并不局限于 Web 浏览器. 这门语言没有输入和输出之类的方法.
ECMAScript 只是对实现这个规范描述的所有方面的一门语言的称呼. 规范包括:
1.2.2 DOM
DOM 是 Document Object Model,文档对象模型的简称. 是一个应用编程接口 (API), 用于在 HTML 中使用扩展的 XML.
DOM 通过创建表示文档的树,让开发者可以随心所欲控制网页的内容和结构:
DOM 并非只能通过 JavaScript 访问, 其他很多语言都实现了.
支持 DOM 对浏览器厂商极为重要.
1.2.3 BOM
BOM 是 Browser Object Model 的缩写. 也是一个 API, 用于支持访问和操作浏览器的窗口.
JavaScript 版本
第2章 HTML 中的 JavaScript
<script>
元素
<script>
元素有八个属性:
两种使用 <script>
的方法:
- 将代码放在
<script>
元素中 (在<script>
元素中的代码被计算完成之前,页面的其他内容不会被加载,也不会被显示) - 使用
src
属性来包含外部文件中的 JavaScript
如:1
<script src="example.js"></script>
注意,外部 JavaScript 文件的扩展名是 .js
, 这是不需要的,因为浏览器不会检查所包含 JavaScript 文件的扩展名.
使用了 src
属性的 <script>
元素不应该再在 <script>
和 </script>
标签中再包含其他 JavaScript 代码,不然行内代码会被忽略.
2.11 标签位置
现代 Web 应用程序通常将所有 JavaScript 引用放在 <body>
元素中页面内容后面:
1 |
|
2.1.2 推迟执行脚本
放在页面底部比较好. defer
属性可能会被忽略.
2.1.3 异步执行脚本
async
属性和 defer
类似. 两者都只适用于外部脚本.
标记为 async
的脚本并不能保证能按照它们出现的次序执行.
async
属性告诉浏览器,不必等脚本下载和执行完后再加载页面, 同样也不必等到该异步脚本下载和执行后在加载其他脚本.
2.1.4 动态加载脚本
向 DOM 中动态添加 script
元素同样可以加载指定的脚本.
2.1.5 XHTML 中的变化
XHTML, Extensible HyperText Markup Language,可扩展超文本标记语言是将 HTML 作为 XML 的应用重新包装的结果.
在 XHTML 中使用 JavaScript 必须指定 type
属性且值为 text/javascript
.
2.1.6 废弃的语法
2.2 行内代码与外部文件
通常认为最佳实践是尽可能将 JavaScript 代码放到外部文件中.
2.3 文档模式
使用 doctype
切换文档模式.
三种文档模式:
- 混杂模式 (quirks mode)
- 标准模式 (standards mode)
- 准标准模式 (almost standards mode)
2.4 <noscript>
元素
第3章 语言基础
3.1 语法
3.1.1 区分大小写
3.1.2 标识符
3.1.3 注释
C 语言的注释.
3.1.4 严格模式
是一种解析和执行模型,将不规范写法抛出.
对整个脚本启用严格模式,在脚本开头加上一行:
1 |
|
其为一条预处理指令.
也可以单独指定一个函数在严格模式下执行:
1 |
|
3.1.5 语句
以分号结尾.
if 语句和 C 一样.
3.2 关键字和保留字
3.3 变量
有三个关键字可以声明变量: var
, const
和 let
.
3.3.1 var 关键字
不初始化的情况下,变量会保存一个特殊值 undefined.
1. var 声明作用域
使用 var
操作符定义的变量会成为包含它的函数的局部变量.
省略 var
操作符定义全局变量,但不推荐这么做.
定义多个变量可以这样写:
1 |
|
2. var 声明提升
1 |
|
等价于:
1 |
|
因此,反复声明也不会报错.
3.3.2 let 声明
let
声明的范围是块作用域, 而 var
声明的范围是函数作用域.
块作用域可以看作是函数作用域的子集.
let
不能重复声明.
1. 暂时性死区
let
不会在作用域中被提升.
4. for 循环中的 let 声明
for
循环的语法同样和 C 中相同.
在 let
出现之前,for
循环定义的迭代变量会渗透到循环体外部.
3.3.3 const 声明
声明时必须初始化,常量. 作用域也是块.
3.3.4 声明风格及最佳实践
不使用 var
.
const
优先,let
次之.
3.4 数据类型
七种类型:
- Undefined
- Null
- Boolean
- Number
- String
- Symbol
- Object
3.4.1 typeof 操作符
返回类型,首字母小写. 参数是一个变量.
3.4.2 Undefined 类型
该类型只有 undefined
这一个特殊值.
一般来说,永远不用显式地给某个变量设置 undefined
值.
对未声明和未初始化的变量使用 typeof
返回值都是 undefined
. 因此,建议在声明变量时进行初始化,来区分未初始化和未声明.
undefined
是一个假值.
3.4.3 Null 类型
Null 类型同样只有 null
这一个特殊值,null
值表示一个空对象指针.
在定义将来要保存对象值的变量时,建议使用 null
来初始化.
undefined
值是由 null
值派生而来的, 因此 ECMA-262 将它们定义为表面相等.
null
也是一个假值.
3.4.4 Boolean 类型
有两个字面值:
true
, 和数值 1 不相等false
, 和数值 0 不相等
区分大小写,
转换函数 Boolean()
:
1 |
|
几个转换函数:
3.4.5 Number 类型
Number 类型使用 IEEE 754 格式表示整数和浮点值.
十进制数直接写.
八进制第一个数字为 0.
十六进制前缀为 0x.
使用八进制和十六进制格式创建的数值在所有数学操作中都被视为十进制数值.
1. 浮点值
因为存储浮点值使用的内存空间是存储整数值的两倍,所以 ECMAScript 总是倾向于把值转换为整数.
也就是说有些浮点值会被自动转换为整数.
浮点值可以用科学记数法表示:
1 |
|
e
可以为大写 E
.
浮点值的精确度最高可达 17 位小数. 但不要用来比较. 0.1 加 0.2 不等于 0.3, 而是 0.300000000000000004.
2. 值的范围
ECMAScript 可以表示的最小值保存在 Number.MIN_VALUE
中.
ECMAScript 可以表示的最大值保存在 Number.MAX_VALUE
中.
无法表示的负数将被表示为 -Infinity
.
无法表示的正数将被表示为 Infinity
.
判断是否有限大 isFinite()
.
3. NaN
NaN, Not a Number, 用于表示本来要返回数值操作失败了.
NaN 不等于 NaN.
1 |
|
可以用 isNaN()
判断.
4. 数值转换
将非数值转换为数值的 3 个函数:
Number()
parseInt
parseFloat
后两个用来处理字符串.
3.4.5 String 类型
可用双引号 "
, 单引号 '
, 反引号标示.
字符串的长度可以通过其 length
属性获取. (如果字符串中包含双字节字符,那么 length 属性返回的可能不准确.)
2. 字符串特点
不可改变 (即,一旦被创建后,其值就不能改变).
修改某个变量中的字符串值,必须先销毁原始的字符串. (销毁过程在后台自动运行)
3. 转换为字符串
几乎所有值都有 toString()
方法.
1 |
|
null
和 undefined
没有 toString()
方法.
toString()
可接收一个参数表示底数 (输出那个进制):
1 |
|
另一个方法是用 String()
.
4. 模板字面量
具体见书
5. 字符串插值
也就是在字符串中插入变量, 使用 ${}
, 如:
1 |
|
插入的值会被 toString()
强制转换为字符串 。
6. 模板字面量标签函数 tag function
见书
7. 原始字符串
见书
3.4.7 Symbol 类型
符号用来创建唯一记号.
1. 符号的基本用法
值为符号的变量需要用 Symbol()
函数初始化:
1 |
|
可以给 Symbol()
传入一个参数作为符号的描述,但是这个值和符号本身的值无关.
Symbol()
函数不能和 new
关键字一起作为构造函数使用.
2. 使用全局符号注册表
见书.
3. 使用符号作为属性
凡是可以使用字符串或数值作为属性的地方,都可以使用符号.
如用作散列的键.
4. 常用内置符号
见书.
3.4.8 Object 类型
ECMAScript 中的对象其实就是一组数据和功能的集合.
对象通过 new
操作符后跟对象类型的名称来创建, 开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法:
1 |
|
可以省略括号但不推荐.
Object 对象所含的属性和方法,见书.
valueOf()
返回对象对应的字符串,数值或布尔值表示.
3.5 操作符
+, -, *, /, %, 以及递增,递减都和 C 相同.
3.5.2 位操作符
ECMAScript 中的所有数值都是以 IEEE 754 64 位格式存储,但位操作并不直接应用到 64 位表示, 而是先把值转换为 32 位整数,再进行位操作,之后再把结果转换为 64 位. 因此只需要考虑 32 位整数.
负值以一种称为 二补数 (或补码) 的二进制编码存储.
符号:
~
, 非&
, 与|
, 或^
, 异或<<
, 左移>>
, 右移>>>
, 无符号右移
3.5.5 指数操作符
**
3.5.8 相等操作符
2. 全等和不全等
===
和 !==
, 推荐使用,不存在类型转换问题.
3.6 语句
if, do-while, while, for, for-in, for-of.
3.6.7 标签语句
3.6.8 break 和 continue
3.6.9 with 语句
将代码作用域设置为特定对象,如:
1 |
|
等价于:
1 |
|
不推荐使用,原因见书.
3.6.10 switch
3.7 函数
语法:
1 |
|
第4章 变量,作用域与内存
4.1 原始值与引用值
JavaScript 不允许直接访问内存位置,因此也就不能直接操作对象所在的内存空间。在操作对象时,实际上操作的是对该对象的引用 (reference) 而非实际的对象本身.
原始值 (primitive value) 是最简单的数据. (Undefined, Null, Boolean, Number, String 和 Symbol)
引用值 (reference value) 是对对象的引用.
4.1.1 动态属性
引用值可以随时添加属性和方法. 而原始值不能.
4.1.2 复制值
引用值复制的值其实是一个指针, 它指向存储在堆内存中的对象.
4.1.3 传递参数
按值传递.
4.1.4 确定类型
使用 instanceof
操作符,判断一个对象是不是某个对象类型:
1 |
|
如:
1 |
|
4.2 执行上下文与作用域
每个上下文都有一个关联的 变量对象 (variable object), 而这个上下文中定义的所有变量和函数都存在于这个对象上。虽然无法是通过代码访问变量对象,但后台处理数据会用到它.
4.3 垃圾回收
垃圾回收就是执行环境负责在代码执行时管理内存.
基本思路就是: 确定哪个变量不会再使用,然后释放它占用的内存. 这个过程是周期性的,即垃圾回收程序每隔一定时间就会自动运行.
垃圾回收程序必须追踪纪录哪个变量还会使用,两种主要的标记方法.
4.3.1 标记清理 (mark-and-sweep)
4.3.2 引用计数 (reference couning)
引用数为 0 时回收.
4.3.3 性能
4.3.4 内存管理
将变量设置为 null 来释放引用.
第5章 基本引用类型
引用类型虽然有点像类,但跟类并不是一个概念.
5.1 Date
创建日期对象:
1 |
|
5.2 RegExp
ECMAScript 通过 RegExp 类型支持正则表达式. 正则表达式使用类似 Perl 的简洁语法来创建:
1 |
|
也可以通过 RegExp 构造函数栏创建:
1 |
|
这种方法,元字符需要二次转义.
5.3 原始值包装类型
5.4 单例内置对象
Global 和 Math.