《JavaScript 闯关记》之 DOM(上)

DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API。DOM 描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。

节点层次

DOM 可以将任何 HTML 或 XML 文档描绘成一个由多层节点构成的结构。节点分为几种不同的类型,每种类型分别表示文档中不同的信息及(或)标记。每个节点都拥有各自的特点、数据和方法,另外也与其他节点存在某种关系。节点之间的关系构成了层次,而所有页面标记则表现为一个以特定节点为根节点的树形结构。以下面的 HTML 为例:

1
2
3
4
5
6
7
8
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

可以将这个简单的 HTML 文档表示为一个层次结构,如图下图所示。

在这个例子中,文档元素是文档的最外层元素,文档中的其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。

每一段标记都可以通过树中的一个节点来表示:HTML 元素通过元素节点表示,特性(attribute)通过特性节点表示,文档类型通过文档类型节点表示,而注释则通过注释节点表示。总共有12种节点类型,这些类型都继承自一个基类型。

阅读更多

《JavaScript 闯关记》之 BOM

ECMAScript 是 JavaScript 的核心,但如果要在 Web 中使用 JavaScript,那么 BOM(浏览器对象模型)则无疑才是真正的核心。BOM 提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。多年来,缺少事实上的规范导致 BOM 有很多问题,因为浏览器提供商会按照各自的想法随意去扩展它。W3C 为了把浏览器中 JavaScript 最基本的部分标准化,已经将 BOM 的主要方面纳入了 HTML5 的规范中。

window 对象

BOM 的核心对象是 window,它表示浏览器的一个实例。在浏览器中,window 对象有双重角色,它既是通过 JavaScript 访问浏览器窗口的一个接口,又是 ECMAScript 规定的 Global 对象。这意味着在网页中定义的任何一个对象、变量和函数,都以 window 作为其 Global 对象,因此有权访问 isNaN()isFinite()parseInt()parseFloat() 等方法。

全局作用域

由于 window 对象同时扮演着 ECMAScript 中 Global 对象的角色,因此所有在全局作用域中声明的变量、函数都会变成 window 对象的属性和方法。来看下面的例子。

1
2
3
4
5
6
7
8
var age = 29;
function sayAge(){
console.log(this.age);
}
console.log(window.age); // 29
sayAge(); // 29
window.sayAge(); // 29

阅读更多

《JavaScript 闯关记》之单体内置对象

ECMA-262 对内置对象的定义是「由 JavaScript 实现提供的、不依赖于宿主环境的对象,这些对象在 JavaScript 程序执行之前就已经存在了」。意思就是说,开发人员不必显式地实例化内置对象,因为它们已经实例化了。前面我们已经介绍了大多数内置对象,例如 ObjectArrayString。ECMA-262 还定义了两个单体内置对象:GlobalMath

Global 对象

Global 对象可以说是 JavaScript 中最特别的一个对象了,因为不管你从什么角度上看,这个对象都是不存在的。Global 对象在某种意义上是作为一个终极的「兜底儿对象」来定义的。换句话说,不属于任何其他对象的属性和方法,最终都是它的属性和方法。所有在全局作用域中定义的属性和函数,都是 Global 对象的属性。本书前面介绍过的那些函数,诸如 isNaN()isFinite()parseInt() 以及 parseFloat(),实际上全都是 Global 对象的方法。除此之外,Global 对象还包含其他一些方法。

阅读更多

《JavaScript 闯关记》之基本包装类型

为了便于操作基本类型值,JavaScript 还提供了3个特殊的引用类型:BooleanNumberString。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。来看下面的例子。

1
2
var s1 = "some text";
var s2 = s1.substring(2);

这个例子中的变量 s1 包含一个字符串,字符串当然是基本类型值。而下一行调用了 s1substring() 方法,并将返回的结果保存在了 s2 中。我们知道,基本类型值不是对象,因而从逻辑上讲它们不应该有方法(尽管如我们所愿,它们确实有方法)。其实,为了让我们实现这种直观的操作,后台已经自动完成了一系列的处理。当第二行代码访问 s1 时,访问过程处于一种读取模式,也就是要从内存中读取这个字符串的值。而在读取模式中访问字符串时,后台都会自动完成下列处理。

  1. 创建 String 类型的一个实例;
  2. 在实例上调用指定的方法;
  3. 销毁这个实例。

可以将以上三个步骤想象成是执行了下列 JavaScript 代码。

1
2
3
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;

经过此番处理,基本的字符串值就变得跟对象一样了。而且,上面这三个步骤也分别适用于 BooleanNumber 类型对应的布尔值和数字值。

阅读更多

《JavaScript 闯关记》之正则表达式

由于本课程的核心是 JavaScript,所以本文着重讲解了「正则表达式」在 JavaScript 中的用法,并未深入「正则表达式」的具体细节。如果您尚不了解「正则表达式」,强烈推荐您先学习 正则表达式30分钟入门教程 http://deerchao.net/tutorials/regex/regex.htm 之后,再进行本课程的学习。

正则表达式(regular expression)是一个描述字符模式的对象,使用正则表达式可以进行强大的模式匹配和文本检索与替换功能。JavaScript 的正则表达式语法是 Perl5 的正则表达式语法的大型子集,所以对于有 Perl 编程经验的程序员来说,学习 JavaScript 中的正则表达式是小菜一碟。

正则表达式的定义

JavaScript 中的正则表达式用 RegExp 对象表示,可以使用 RegExp() 构造函数来创建 RegExp 对象,不过 RegExp 对象更多是通过字面量的语法来创建,使用下面类似 Perl 的语法,就可以创建一个正则表达式。例如:

1
2
3
4
5
// 推荐写法
var expression = / pattern / flags ;
// 不推荐写法
var expression = new RegExp(pattern, flags);

阅读更多