第 1 章 JavaScript 简史
1.1 JavaScript 的起源
JavaScript 是 Netscape 公司与 Sun 公司合作开发的。
JavaScript 是 ECMAScript 标准的一种实现,但在一般表述中,这两者是指同一种编程语言。
1.2 DOM
DOM(Document Object Model,文档对象模型),是一套对文档的内容进行抽象和概念化的方法。
通过 DOM 可以对文档内的某些实际内容进行查询和操控。
1.3 浏览器战争
1.3.1 DHTML
DHTML(Dynamic HMTL,动态 HTML),是描述 HTML、CSS 和 JavaScript 技术组合的术语。其背后的含义是:
- 利用 HTML 把网页标记为各种元素;
- 利用 CSS 设置元素样式和它们显示的位置;
- 利用 JavaScript 实时地操控页面和改变样式。
1.3.2 浏览器之间的冲突
Netscape 公司和 Microsoft 公司的浏览器的 DOM 的差异,导致了当时 DHTML 技术的难以实现。
1.4 制定标准
W3C 于 1998 年 10 月完成了“第 1 级 DOM”(DOM Level 1)标准,这种标准化的 DOM 可以让任何一种程序设计语言对使用任何一种标记语言编写出来的任何一种文档进行操控。
1.4.1 浏览器以外的考虑
DOM 是一种 API(Application Programming Interface,应用程序编程接口),也是一种已经得到有关各方共同认可的基本约定。
W3C 对 DOM 的定义是:“一个与系统平台和编程语言无关的接口,程序和脚本可以通过这个接口动态的访问和修改文档的内容、结构和样式。”
1.4.2 浏览器战争的结局
由于 Windows 操作系统的成功,Netscape 公司输了。战争促进了 DOM 标准的最终制定。
1.4.3 崭新的起点
WebKit 是 Safari 和 Chrome 采用的一个开源 Web 浏览器引擎;它与另一个开源引擎——FireFox 的核心 Gecko,共同促进了 IE 的核心 Trident 等专有浏览器引擎逐步向 Web 标准靠拢。
1.5 小结
略。
第 2 章 JavaScript 语法
2.1 准备工作
使用 JavaScript 的两种方式:
- 将代码放到文档
<head>
标签中的<script>
标签之间; - 将代码保存为扩展名 .js 的独立文件,然后在文档的
<head>
标签中添加<script>
标签,并使用<script>
标签的 src 属性指向该文件。
最好的做法是把 <script>
标签放到 HTML 文档的最后,</body>
标签之前。
程序语言分为解释型和编译型两大类。Java 或 C++ 等语言需要一个编译器(compiler)。编译器是一种程序,能够把 Java 等高级语言编写出来的源代码翻译为直接在计算机上执行的文件。
解释型程序设计语言不需要编译器,仅需要解释器,对于 JavaScript 语言,一般由浏览器负责完成有关的解释和执行工作。
2.2 语法
2.2.1 语句
JavaScript 编写的脚本又一系列指令构成,这些指令叫作语句(statement)。
各条语句放在不同行就可以分隔开,如果多条语句要放在同一行,必须使用分号 ;
分隔;建议每条语句的末尾都加分号。
2.2.2 注释
脚本中有一些需要解释器直接忽略的仅供参考或提醒的信息,这类语句就是注释(comment)。
- 单行注释开头使用双斜线
//
; - 多行注释需要将注释内容使用
/*
和*/
包裹起来。
2.2.3 变量
人们把那些会发生变化的东西称为变量(variable),例如人的心情、年龄等。
把值存入变量的操作称为赋值(assignment)。
JavaScript 允许直接对变量赋值而无需事先声明这个变量,这在很多程序设计语言中是不允许的。
要求在使用任何变量之前必须先对它做出“介绍”,就叫作声明(declare)。
在 JavaScript 中,如果对某个变量赋值之前未声明该变量,赋值操作将自动声明该变量。虽然如此,但提前声明变量是良好的习惯,另外还关乎于变量的作用域与变量声明提前等影响。
声明变量使用 var
操作符(ES6 标准之前的方式)。另外:
- 可以用一条语句一次声明多个变量,变量名之间使用逗号
,
分割; - 变量的声明和赋值操作可以同时进行;
在 JavaScript 中变量名区分大小写;变量名中只能使用字母、数字、下划线 _
和美元符号 $
,且第一个字符不能为数字。
变量名一般使用驼峰格式(camel case)或在词语之间使用下划线连接的方式命名。
在 JavaScript 中直接在代码中写出的数据称为字面量(literal),字面量除了表示自己以外不能表示任何别的东西……“它就是它!”嗯……
2.2.4 数据类型
有些其他语言要求在声明变量的同时声明变量的数据类型,这种做法称为类型声明(typing)。
必须明确类型声明的语言称为强类型(strongly typed)语言;而 JavaScript 不需要进行类型声明,因此它是一种弱类型(weakly typed)语言。这意味着可以在任何阶段改变变量的数据类型。
JavaScript 中的重要数据类型有:
1. 字符串
字符串(string)类型由零个或多个字符构成(零个的称为“空字符串”),字符串必须包在引号里,单引号双引号皆可,一般推荐单引号,并且整个脚本要一致,这才是良好的编程习惯。
如果要表示的字符串中包含单引号,为了避免解释器认为它是整个字符串的结尾,则将其放在双引号中,反之则反。但是一般推荐使用转义符来转义(escaping)有代码含义的字符,在 JavaScript 中,使用反斜线 \
对字符进行转义。
2. 数值
数值(number)类型包含整数和带任意位小数的浮点数。在数值前面加一个减号 -
表示该数值为负数。
3. 布尔值
布尔(boolean)类型只包含两个值—— true
和 false
。
布尔值不是字符串,千万不要把布尔值使用引号包起来。'false'
和 false
值两码事。
备注:书中只简单提到三种基本数据类型,没有提到另外两种基本数据类型 undefined 和 null,以及复杂数据类型 object。
2.2.5 数组
字符串、数值和布尔值都是标量(scalar)。如果某个变量是标量,它在任意时刻就只能有一个值。如果想用一个变量来存储一组值,就需要使用数组(array)。
数组是指用一个变量表示一个值的集合,集合中的每个值都是这个数组的一个元素(element)。
声明数组有两种方式:
- 使用
Array
关键字,声明数组的同时可以指定数组的初始元素个数,也就是数组的长度(length); - 使用字符字面量的方式,即使用一对中括号来表示数组;
向数组中添加元素的操作称为填充(populating);在填充数组时,需要给出新元素的值以及新元素在数组中的位置,这个位置就是这个元素的下标(index);下标从 0 开始,数组里每个元素都有下标,使用下标时必须用方括号将其括起来。
前面提到的两种声明数组的方法都可以在声明的同时,对数组进行填充操作。
数组元素可以保存任何类型的数据,同一数组的元素也可以保存不同类型的数据;如果数组的元素中保存了另一个数组,这种数组被称为多元数组,多元数组虽然强大,但一般建议使用对象将复杂数据保存在数组中。
在填充数组时只给出了元素的值,其下标为默认的数值,这个数组就是一个传统数组;而在填充时为元素同时添加下标和值,且下标不是数值而是字符串,这种数组称为关联数组。填充元素时将下标设置为字符串,实际与为数组添加属性的操作相同。
备注:其实关联数组与 JSON 格式的数据类似,但是不推荐使用关联数组。
2.2.6 对象
与数组类似,对象也是使用一个名字表示一组值。对象的每个值都是对象的一个属性。
创建对象也有两种方式:
- 使用
Object
关键字; - 使用字符字面量的方式,即使用一对花括号来表示对象。
访问、添加或修改对象的属性可以使用点号 .
,也可以使用中括号,中括号内的属性名必须为字符串,是要用引号括起来的。使用对象直接量的方式可以同时声明对象和为对象添加属性;属性的值可以是任何数据类型。
2.3 操作
对数据进行计算和处理的动作称为操作(operation)。
算数操作符
加 +
、减 -
、乘 *
、除 /
操作,都是算术操作(arithmetic operation);每一种都必须借助于相应的操作符(operator)才能完成,操作符是 JavaScript 为完成各种操作而定义的一些符号。
可以把多种操作组合在一起使用;为避免产生歧义或提高运算优先级,可以使用括号把不同的操作分割开。
为一个变量加 1 可以简写为 ++
,减法操作也可以如此,再复习一遍前置 ++
或 --
和后置 ++
或 --
的区别:
- 前置
++
/--
先计算,后赋值; - 后置
++
/--
先赋值,后计算。
这里要重点一下加法操作符,当两个操作数都为数字时便进行加法操作,如果有一个操作数是字符串时,便将另一个操作数转换为字符串并将两个操作数首位相连地拼接(concatenation)为一个字符串。
值或变量包含自身的一次加法(或拼接)/减法操作后的赋值可以简写为 +=
/ -=
。
2.4 条件语句
JavaScript 使用条件语句(conditional statement)来做判断。
最常见的条件语句是 if
语句,条件必须放到 if
后面的圆括号中,条件的求值结果永远是一个布尔值;花括号中的语句,只要在给定条件的求值结果为 true
的情况下才会执行。
如果 if
语句后面只有一条语句,可以不加花括号,但是并不推荐这样做。
2.4.1 比较操作符
比较操作符包括大于 >
、小于 <
、大于或等于 >=
、小于或等于 <=
、相等 ==
、全等 ===
、不相等 !=
和不全等 !==
。
一个等于号 =
是赋值操作符,不是比较操作符,所以不要在条件判断时使用错;如果使用了赋值操作符进行了条件判断,会使判断条件的结果最终取决于被赋值的变量转换后的布尔值。
相等/不相等和全等/不全等的区别简单的说是:相等操作符不表示严格相等,在比较时会发生两个操作数的类型转换;而全等是严格相等,需要数据类型和值完全相等才会返回 true
,比较时是不会发生数据类型转换的。
2.4.2 逻辑操作符
JavaScript 允许把条件语句里的操作组合在一起。判断两个或更多个条件的成立与否的操作,称为逻辑比较(operand)。
逻辑与操作符 &&
只要在它的两个操作数都为真时才会返回 true
。
逻辑或操作符 ||
只要有一个操作数为真则会返回 true
。
逻辑非操作符 !
只能用于单个操作数,其结果是将操作数返回的布尔值取反。
2.5 循环语句
循环语句可以反复多次执行同一段代码,只要给定条件仍然能得到满足,包含在循环语句中的代码就将重复执行;一旦给定条件返回值不再为 true
,则停止循环。
2.5.1 while 循环
只要圆括号内的给定条件求值为 true
,则包含在花括号里的代码反复执行;一般会在花括号里设定停止循环的条件。
do...while 循环
与 while
循环的区别是,在循环条件求值之前,包含在花括号里的代码至少会执行一次,然后再判断循环条件是否成立。
2.5.2 for 循环
for
循环是 while
循环的一种变体。
for
循环最常见的用途是对某个数组里的全体元素进行遍历处理,一般情况下,都会设定循环停止的条件为,比如循环轮次变量小于数组的最大长度,即 i < arr.length
。
2.6 函数
如果需要多次使用同一段代码,可以把它们封装成一个函数(function),函数就是一组允许在代码里随时调用的语句,每个函数实际上是一个短小的脚本。
一般情况下,需要先对函数做出定义再调用它们;当然也有自调用的匿名函数这种二般的情况。
函数可以接收传递进来的数据,并使用这些数据完成预定的操作,这些传递进函数的数据称为参数(argument)。
在定义函数时,可以为其声明任意多个参数,它们之间需要使用逗号分隔;在函数内部可以像使用普通变量一般使用任何一个传递进来的参数。
函数不仅可以接收数据,还可以返回数据,返回数据使用 return
关键字,当结果返回完毕后,函数也将停止运行。
变量命名推荐使用下滑线分隔单词,而函数命名推荐使用驼峰格式,这样可以一目了然的分辨变量和函数。
变量的作用域
变量可以是全局的,也可以是局部的。
全局变量(global variable)可以在脚本中的任何位置被引用;全局变量的作用域是整个脚本。
局部变量(local variable)只存在于声明它的函数内部,在该函数外部是无法引用这个局部变量的;局部变量的作用域仅限于某个特定的函数内部。
前面提到变量声明时,应该使用 var
关键字,这样做就是为了明确变量的作用域。不使用 var
关键字声明的变量属于全局变量,不论这个变量是在脚本的什么位置声明的。而使用 var
关键字,变量就将成为一个局部变量,除非它不是在某个函数中。
函数在行为方面应该像一个自给自足的脚本,在定义一个函数时,一定要把其内部变量全部明确地声明为局部变量。
2.7 对象
对象(object)是自包含的数据集合,包含在对象里的数据可以通过两种形式访问——属性(property)和方法(method),对象就是由一些属性和方法组合在一起构成的数据实体:
- 属性是隶属于某个特定对象的变量;
- 方法是只有某个特定对象才能调用的函数。
要访问对象的属性或方法,可以使用点号。
实例(instance)是对象的具体个体;将对象实例化后,便可以访问对象的属性和方法。
为给定对象创建一个新实例需要使用 new
关键字。
在 JavaScript 中,由用户创建的对象被称为用户自定义对象(user-defined object);而语言提供的一系列预先定义好的对象称为内建对象(native object)。
2.7.1 内建对象
常见的内建对象如前面提到的数组对象(Array),以及常用的数学对象(Math)和日期对象(Date)等。
所有对象都是 Object 对象的实例。
具有抽象化的对象在命名时首字母一般都是大写。
2.7.2 宿主对象
有一些非 JavaScript 提供的,但也是预先定义好的对象,它们是由 JavaScript 的运行环境提供的,这些对象称为宿主对象(host object)。
例如在浏览器环境中的 window 对象,在 Node.js 环境中是没有的。这本书主要讲的也是一个浏览器提供的宿主对象——Document 对象。
2.8 小结
略。
第 3 章 DOM
3.1 文档:DOM 中的“D”
指的是 Document,即文档。当创建一个网页并把它加载到 Web 浏览器中时,浏览器便把网页文档转换为一个文档对象。
3.2 对象:DOM 中的“O”
指的是 Object,即对象。宿主对象 window 是最基础的对象之一,它对应着浏览器窗口本身,这个对象的属性和方法通常统称为 BOM(Browser Object Model,浏览器对象模型)。
3.3 模型:DOM 中的“M”
指的是 Model,意思是“模型”,但更形象的描述是“Map”,即地图。简单理解,地图标明了文档中各个节点的方位和彼此之间的关系,JavaScript 可以依照这个地图,来访问对应的元素。
书中用 DOM 树来更清楚的表现了网页的结构。
3.4 节点
节点(node)表示网络中的一个连接点,一个网络就是由一些节点构成的集合。
DOM 也是由节点构成的集合,在 DOM 中主要有三种节点:元素节点、文本节点以及属性节点。
3.4.1 元素节点
元素节点(element node)是 DOM 的主要组成部分。
标签的名字就是元素的名字,在一般情况下,标签就等于元素。
3.4.2 文本节点
在文档中,文本节点(text node)总是被包含在元素节点的内部,但并非所有元素节点都包含有文本节点。
3.4.3 属性节点
属性节点(attribute node)用来对元素节点作出更具体的描述。属性总是被放在起始标签中,所以属性节点总是被包含在元素节点中。但并非所有元素都包含属性。
3.4.4 CSS
通过 CSS(Cascading Style Sheet,层叠样式表)可以告诉浏览器如何显示一份文档。
在 CSS 中,也把文档内容视为一棵节点树,节点树上的各个元素都将继承(inheritance)其父元素的样式属性。
为了把某个或多个元素与其他元素区别开,需要使用标签的 id 或 class 属性。
1. class 属性
可以在所有元素上任意应用 class 属性。class 属性在元素所在的文档中不具有唯一性。
2. id 属性
id 属性的用途是给网页里的某个元素加上一个独一无二的标识符,也就是说在元素所在的整个文档中,id 属性具有唯一性。
3.4.5 获取元素
有 3 种 DOM 方法可以获取元素节点,分别是通过元素 ID、通过标签名和通过类名来获取。
1. getElementById
语法:
document.getElementById(id)
该方法返回一个拥有指定 id 属性的元素节点对应的对象。它是 document 对象特有的函数。
2. getElementsByTagName
语法:
document.getElementByTagName(tag)
该方法返回的是一个对象数组,每个对象对应文档中有指定标签名的元素。
该方法允许一个通配符 *
做为其参数,这样可以将文档中的所有标签元素全部返回为一个数组。
3. getElementsByClassName
语法:
document.getElementByClassName(class)
该方法为 HTML5 DOM 中新增的方法,可以通过标签 class 属性中的类名来访问元素,返回值是一个对象数组,每个对象对应文档中具有指定类名的元素。
通过这个方法还可以查找带有多个类名的元素,不同的类名可以使用空格分割。
由于通过类名访问元素的方法较新,书中还写了一个函数以兼容老浏览器:
通过标签名和类名查找元素的方法都可以和通过 id 查找的方法结合使用,以缩小查找范围。
3.4.6 盘点知识点
- 一份文档就是一棵节点树。
- 节点按类型分为:元素节点、属性节点和文本节点。
-
getElementById
将返回一个对象,该对象对应着文档里的一个特定元素节点。 -
getElementByTagName
和getElementByClassName
将返回一个对象数组,它们分别对应着文档里一组特定的元素节点。 - 每个节点都是一个对象。
3.5 获取和设置属性
3.5.1 getAttribute
语法:
object.getAttribute(attribute)
这个函数只接收一个参数,就是要查询的属性名。该方法不属于 document 对象,只能通过元素节点对象调用。
当需要通过 if
语句判断某个值是否存在而进行后面的操作时,
网友评论