NodeList 接口,HTMLCollection
接口
节点都是单个对象,有时需要一种数据结构,能够容纳多个节点。DOM
提供两种节点集合,用于容纳多个节点:NodeList和HTMLCollection。
这两种集合都属于接口规范。许多 DOM
属性和方法,返回的结果是NodeList实例或HTMLCollection实例。主要区别是,NodeList可以包含各种类型的节点,HTMLCollection只能包含
HTML 元素节点。
NodeList 接口
概述
NodeList实例是一个类似数组的对象,它的成员是节点对象。通过以下方法可以得到NodeList实例。
Node.childNodes
document.querySelectorAll()等节点搜索方法
1document.body.childNodes instanceof NodeList // true
NodeList实例很像数组,可以使用length属性和forEach方法。但是,它不是数组,不能使用pop或push之类数组特有的方法。
123456var children = document.bo ...
Node 接口
所有 DOM 节点对象都继承了 Node 接口,拥有一些共同的属性和方法。这是
DOM 操作的基础。
属性
Node.prototype.nodeType
nodeType属性返回一个整数值,表示节点的类型。
1document.nodeType // 9
上面代码中,文档节点的类型值为9。
Node 对象定义了几个常量,对应这些类型值。
1document.nodeType === Node.DOCUMENT_NODE // true
上面代码中,文档节点的nodeType属性等于常量Node.DOCUMENT_NODE。
不同节点的nodeType属性值和对应的常量如下。
文档节点(document):9,对应常量Node.DOCUMENT_NODE
元素节点(element):1,对应常量Node.ELEMENT_NODE
属性节点(attr):2,对应常量Node.ATTRIBUTE_NODE
文本节点(text):3,对应常量Node.TEXT_NODE
文档片断节点(DocumentFragment):11,对应常量Node.DOCUMENT_FRAG ...
DOM 概述
DOM
DOM 是 JavaScript 操作网页的接口,全称为“文档对象模型”(Document
Object Model)。它的作用是将网页转为一个 JavaScript
对象,从而可以用脚本进行各种操作(比如增删内容)。
浏览器会根据 DOM 模型,将结构化文档(比如 HTML 和
XML)解析成一系列的节点,再由这些节点组成一个树状结构(DOM
Tree)。所有的节点和最终的树状结构,都有规范的对外接口。
DOM 只是一个接口规范,可以用各种语言实现。所以严格地说,DOM 不是
JavaScript 语法的一部分,但是 DOM 操作是 JavaScript 最常见的任务,离开了
DOM,JavaScript 就无法控制网页。另一方面,JavaScript 也是最常用于 DOM
操作的语言。后面介绍的就是 JavaScript 对 DOM 标准的实现和用法。
节点
DOM 的最小组成单位叫做节点(node)。文档的树形结构(DOM
树),就是由各种不同类型的节点组成。每个节点可以看作是文档树的一片叶子。
节点的类型有七种。
Document:整个文档树的顶层节点
...
Promise 对象
概述
Promise 对象是 JavaScript
的异步操作解决方案,为异步操作提供统一接口。它起到代理作用(proxy),充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口。Promise
可以让异步操作写起来,就像在写同步操作的流程,而不必一层层地嵌套回调函数。
注意,本章只是 Promise
对象的简单介绍。为了避免与后续教程的重复,更完整的介绍请看《ES6 标准入门》的《Promise
对象》一章。
首先,Promise 是一个对象,也是一个构造函数。
12345function f1(resolve, reject) { // 异步代码...}var p1 = new Promise(f1);
上面代码中,Promise构造函数接受一个回调函数f1作为参数,f1里面是异步操作的代码。然后,返回的p1就是一个
Promise 实例。
Promise 的设计思想是,所有异步任务都返回一个 Promise 实例。Promise
实例有一个then方法,用来指定下一步的回调函数。
12var p1 = new Promis ...
定时器
JavaScript
提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列添加定时任务。
setTimeout()
setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。
1var timerId = setTimeout(func|code, delay);
上面代码中,setTimeout函数接受两个参数,第一个参数func|code是将要推迟执行的函数名或者一段代码,第二个参数delay是推迟执行的毫秒数。
123456console.log(1);setTimeout('console.log(2)',1000);console.log(3);// 1// 3// 2
上面代码会先输出1和3,然后等待1000毫秒再输出2。注意,console.log(2)必须以字符串的形式,作为setTimeout的参数。
如果推迟执行的是函数,就直接将函数名,作为setTimeout的参数。
1 ...
异步操作概述
单线程模型
单线程模型指的是,JavaScript 只在一个线程上运行。也就是说,JavaScript
同时只能执行一个任务,其他任务都必须在后面排队等待。
注意,JavaScript 只在一个线程上运行,不代表 JavaScript
引擎只有一个线程。事实上,JavaScript
引擎有多个线程,单个脚本只能在一个线程上运行(称为主线程),其他线程都是在后台配合。
JavaScript 之所以采用单线程,而不是多线程,跟历史有关系。JavaScript
从诞生起就是单线程,原因是不想让浏览器变得太复杂,因为多线程需要共享资源、且有可能修改彼此的运行结果,对于一种网页脚本语言来说,这就太复杂了。如果
JavaScript 同时有两个线程,一个线程在网页 DOM
节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?是不是还要有锁机制?所以,为了避免复杂性,JavaScript
一开始就是单线程,这已经成了这门语言的核心特征,将来也不会改变。
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延 ...
严格模式
除了正常的运行模式,JavaScript 还有第二种运行模式:严格模式(strict
mode)。顾名思义,这种模式采用更加严格的 JavaScript 语法。
同样的代码,在正常模式和严格模式中,可能会有不一样的运行结果。一些在正常模式下可以运行的语句,在严格模式下将不能运行。
设计目的
早期的 JavaScript
语言有很多设计不合理的地方,但是为了兼容以前的代码,又不能改变老的语法,只能不断添加新的语法,引导程序员使用新语法。
严格模式是从 ES5 进入标准的,主要目的有以下几个。
明确禁止一些不合理、不严谨的语法,减少 JavaScript
语言的一些怪异行为。
增加更多报错的场合,消除代码运行的一些不安全之处,保证代码运行的安全。
提高编译器效率,增加运行速度。
为未来新版本的 JavaScript 语法做好铺垫。
总之,严格模式体现了 JavaScript
更合理、更安全、更严谨的发展方向。
启用方法
进入严格模式的标志,是一行字符串use strict。
1'use strict';
老版本的引擎会把它当作一行普通字符串,加以忽略。新 ...
Object 对象的相关方法
JavaScript
在Object对象上面,提供了很多相关方法,处理面向对象编程的相关操作。本章介绍这些方法。
Object.getPrototypeOf()
Object.getPrototypeOf方法返回参数对象的原型。这是获取原型对象的标准方法。
123var F = function () {};var f = new F();Object.getPrototypeOf(f) === F.prototype // true
上面代码中,实例对象f的原型是F.prototype。
下面是几种特殊对象的原型。
123456789// 空对象的原型是 Object.prototypeObject.getPrototypeOf({}) === Object.prototype // true// Object.prototype 的原型是 nullObject.getPrototypeOf(Object.prototype) === null // true// 函数的原型是 Function.prototyp ...
对象的继承
面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B
对象,就能直接拥有 B
对象的所有属性和方法。这对于代码的复用是非常有用的。
大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript
语言的继承不通过 class,而是通过“原型对象”(prototype)实现,本章介绍
JavaScript 的原型链继承。
ES6 引入了 class 语法,基于 class 的继承不在这个教程介绍,请参阅《ES6
标准入门》一书的相关章节。
原型对象概述
构造函数的缺点
JavaScript
通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。
123456789function Cat (name, color) { this.name = name; this.color = color;}var cat1 = new Cat('大毛', '白色');cat1.name // '大毛'cat1 ...
this 关键字
涵义
this关键字是一个非常重要的语法点。毫不夸张地说,不理解它的含义,大部分开发任务都无法完成。
前一章已经提到,this可以用在构造函数之中,表示实例对象。除此之外,this还可以用在别的场合。但不管是什么场合,this都有一个共同点:它总是返回一个对象。
简单说,this就是属性或方法“当前”所在的对象。
1this.property
上面代码中,this就代表property属性当前所在的对象。
下面是一个实际的例子。
123456789var person = { name: '张三', describe: function () { return '姓名:'+ this.name; }};person.describe()// "姓名:张三"
上面代码中,this.name表示name属性所在的那个对象。由于this.name是在describe方法中调用,而describe方法所在的当前对象是person,因此this指向person,t ...