JavaScript高级程序设计(第4版)阅读路线图
2024-09-05 19:46:36 0 举报
AI智能生成
JavaScript高级程序设计(第4版)阅读路线图和笔记
作者其他创作
大纲/内容
基本知识
第1章 什么是JavaScript
简短的历史回顾
JavaScript实现
ECMAScript
DOM
BOM
JavaScript版本
第2章 HTML中的JavaScript
<script>元素
标签位置
推迟执行脚本
异步执行脚本
动态加载脚本
XHTML中的变化
废弃的语法
行内代码与外部文件
文档模式
<noscript元素>
第3章 语言基础
语法
区分大小写
标识符
注释
严格模式
语句
关键字与保留字
变量
var关键字
let声明
const声明
声明风格及最佳实践
数据类型
typeof操作符
undefined类型
null类型
boolean类型
number类型
string类型
symbol类型
object类型
操作符
一元操作符
位操作符
布尔操作符
乘性操作符
指数操作符
加性操作符
关系操作符
相等操作符
条件操作符
赋值操作符
逗号操作符
语句
if语句
do-while语句
while语句
for语句
for-in语句
for-of语句
标签语句
break和continue语句
with语句
switch语句
函数
第4章 变量、作用域与内存
原始值与引用值
动态属性
复制值
传递参数
确定类型
执行上下文与作用域
作用域链增强
变量声明
垃圾回收
标记清理
引用计数
性能
内存管理
第5章 基本引用类型
Date
继承的方法
日期格式化方法
日期/时间组件方法
RegExp
RegExp实例属性
RegExp实例方法
RegExp构造函数属性
模式局限
原始值包装类型
Boolean
Number
String
单例内置对象
Global
Math
第6章 集合引用类型
Object
Array
创建数组
数组空位
数组索引
检测数组
迭代器方法
复制和填充方法
转换方法
栈方法
队列方法
排序方法
操作方法
搜索和位置方法
迭代方法
归并方法
定型数组
历史
ArrayBuffer
DataView
定型数组
Map
基本API
顺序与迭代
选择Object还是Map
WeakMap
基本API
弱键
不可迭代键
使用弱映射
Set
基本API
顺序与迭代
定义正式集合操作
WeakSet
基本API
弱值
不可迭代值
使用弱集合
迭代与扩展操作
进阶内容
第7章 迭代器与生成器
理解迭代
迭代器模式
可迭代协议
迭代器协议
自定义迭代器
提前终止迭代器
生成器
生成器基础
通过yeild中断执行
生成器作为默认迭代器
提前终止生成器
第8章 对象、类与面向对象编程
理解对象
属性的类型
数据属性
数据属性有4个特性描述它们的行为
[[Configurable]]
表示属性是否可以通过 delete 删除并重新定义,
是否可以修改它的特性,以及是否可以把它改为访问器属性。
是否可以修改它的特性,以及是否可以把它改为访问器属性。
[[Enumerable]]
表示属性是否可以通过 for-in 循环返回
[[Writable]]
表示属性的值是否可以被修改
[[Value]]
属性实际的值,默认值为 undefined
修改属性的默认特性
必须使用 Object.defineProperty()方法
访问器属性
访问器属性也有 4 个特性描述它们的行为
[[Configurable]]
[[Enumerable]]
[[Get]]
获取函数,在读取属性时调用。默认值为 undefined。
[[Set]]
设置函数,在写入属性时调用。默认值为 undefined。
定义多个属性
Object.defineProperties()方法
读取属性的特性
使用 Object.getOwnPropertyDescriptor()方法可以取得指定属性的属性描述符
这个方法接收两个参数:属性所在的对象和要取得其描述符的属性名。
返回值是一个对象,对于访问器属性包含configurable、enumerable、get 和 set 属性,
对于数据属性包含 configurable、enumerable、writable 和 value 属性。
对于数据属性包含 configurable、enumerable、writable 和 value 属性。
ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()静态方法
接收一个参数: 属性所在的对象
这个方法实际上会在每个自有属性上调用 Object.getOwnPropertyDescriptor()
并在一个新对象中返回它们
并在一个新对象中返回它们
合并对象
合并的意义
JavaScript 开发者经常觉得“合并”(merge)两个对象很有用。
更具体地说,就是把源对象所有的本地属性一起复制到目标对象上。
有时候这种操作也被称为“混入”(mixin),因为目标对象通过混入源对象的属性得到了增强。
更具体地说,就是把源对象所有的本地属性一起复制到目标对象上。
有时候这种操作也被称为“混入”(mixin),因为目标对象通过混入源对象的属性得到了增强。
Object.assign()方法
接收一个目标对象和一个或多个源对象作为参数
将每个源对象中可枚举(Object.propertyIsEnumerable()返回 true)
和自有(Object.hasOwnProperty()返回 true)属性复制到目标对象
和自有(Object.hasOwnProperty()返回 true)属性复制到目标对象
以字符串和符号(Symbol)为键的属性会被复制。
因为Map可以用函数和对象为键。
因为Map可以用函数和对象为键。
Object.assign()实际上对每个源对象执行的是浅复制
如果多个源对象都有相同的属性,则使用最后一个复制的值
从源对象访问器属性取得的值,比如获取函数getter,会作为一个静态值赋给目
标对象。换句话说,不能在两个对象间转移获取函数和设置函数。
标对象。换句话说,不能在两个对象间转移获取函数和设置函数。
对象标识及相等判定
===操作符
ECMAScript 6 规范新增了 Object.is()
增强的对象语法
属性值简写
可计算属性
简写方法名
对象解构
对象解构就是使用与对象匹配的结构来实现对象属性赋值
解构在内部使用函数 ToObject()(不能在运行时环境中直接访问)把源数据结构转换为对象。
创建对象
概述
ES6 的类都仅仅是封装了 ES5.1 构造函数加原型继承的语法糖
工厂模式
用于抽象创建特定对象的过程
工厂模式虽然可以解决创建多个类似对象的问题,
但没有解决对象标识问题(即新创建的对象是什么类型)
但没有解决对象标识问题(即新创建的对象是什么类型)
构造函数模式
可以自定义构造函数,以函数的形式
为自己的对象类型定义属性和方法
为自己的对象类型定义属性和方法
创建的实例,应使用 new 操作符
(1) 在内存中创建一个新对象(开辟内存)
(2) 这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性
(3) 构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)
(4) 执行构造函数内部的代码(给新对象添加属性)。
(5) 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
构造函数也是函数
构造函数与普通函数唯一的区别就是调用方式不同
任何函数只要使用 new 操作符调用就是构造函数,
而不使用 new 操作符调用的函数就是普通函数
而不使用 new 操作符调用的函数就是普通函数
构造函数的问题
构造函数的主要问题在于,
其定义的方法会在每个实例上都创建一遍
其定义的方法会在每个实例上都创建一遍
因此不同实例上的函数虽然同名却不相等
要解决这个问题,可以把函数定义转移到构造函数外部
原型模式
每个函数都会创建一个 prototype 属性,
这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法
这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法
实际上,这个对象就是通过调用构造函数创建的对象的原型
理解原型
无论何时,只要创建一个函数,就会按照特定的规则为这个函数创建一个 prototype 属性(指向原型对象)。
默认情况下,所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数。
例子,Person.prototype.constructor 指向 Person
默认情况下,所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数。
例子,Person.prototype.constructor 指向 Person
构造函数、原型对象和实例是 3 个完全不同的对象
实例与构造函数原型之间有直接的联系,但实例与构造函数之间没有。
constructor 属性只存在于原型对象,通过实例对象沿原型链可以访问到的
原型层级
在通过对象访问属性时,会按照这个属性的名称开始搜索。
搜索开始于对象实例本身。如果在这个实例上发现了给定的名称,则返回该名称对应的值。
如果没有找到这个属性,则搜索会沿着指针进入原型对象,然后在原型对象上找到属性后,再返回对应的值。
搜索开始于对象实例本身。如果在这个实例上发现了给定的名称,则返回该名称对应的值。
如果没有找到这个属性,则搜索会沿着指针进入原型对象,然后在原型对象上找到属性后,再返回对应的值。
只要给对象实例添加一个属性,这个属性就会遮蔽(shadow)原型对象上的同名属性,
也就是虽然不会修改它,但会屏蔽对它的访问。
也就是虽然不会修改它,但会屏蔽对它的访问。
使用 delete 操作符可以完全删除实例上的属性
hasOwnProperty()方法用于确定某个属性是在实例上还是在原型对象上。
这个方法是继承自 Object的,会在属性存在于调用它的对象实例上时返回 true
这个方法是继承自 Object的,会在属性存在于调用它的对象实例上时返回 true
注意 ECMAScript 的 Object.getOwnPropertyDescriptor()方法只对实例属性有效。
要取得原型属性的描述符,就必须直接在原型对象上调用 Object.getOwnPropertyDescriptor()。
要取得原型属性的描述符,就必须直接在原型对象上调用 Object.getOwnPropertyDescriptor()。
原型和 in 操作符
有两种方式使用 in 操作符:单独使用和在 for-in 循环中使用。
在单独使用时,in 操作符会在可以通过对象访问指定属性时返回 true,无论该属性是在实例上还是在原型上。
在单独使用时,in 操作符会在可以通过对象访问指定属性时返回 true,无论该属性是在实例上还是在原型上。
for-in 循环中使用 in 操作符时,可以通过对象访问且可以被枚举的属性都会返回,
包括实例属性和原型属性
包括实例属性和原型属性
要获得对象上所有可枚举的实例属性,可以使用 Object.keys()方法
属性枚举顺序
for-in 循环、Object.keys()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()以及 Object.assign()在属性枚举顺序方面有很大区别
for-in 循环和 Object.keys()
的枚举顺序是不确定的,取决于 JavaScript 引擎,可能因浏览器而异
的枚举顺序是不确定的,取决于 JavaScript 引擎,可能因浏览器而异
bject.getOwnPropertyNames()、Object.getOwnPropertySymbols()和 Object.assign()
的枚举顺序是确定性的。
的枚举顺序是确定性的。
使用原型对象的好处是,
在它上面定义的属性和方法可以被对象实例共享
在它上面定义的属性和方法可以被对象实例共享
对象迭代
Object.values()返回对象值的数组(符号属性会被忽略)
Object.entries()返回键/值对的数组(符号属性会被忽略)
继承
原型链
重温一下构造函数、原型和实例的关系
每个构造函数都有一个原型对象,
原型有一个属性指回构造函数,
而实例有一个内部指针指向原型
原型有一个属性指回构造函数,
而实例有一个内部指针指向原型
原型链的基本构想
如果原型是另一个类型的实例呢?
那就意味着这个原型本身有一个内部指针指向另一个原型,
相应地另一个原型也有一个指针指向另一个构造函数
那就意味着这个原型本身有一个内部指针指向另一个原型,
相应地另一个原型也有一个指针指向另一个构造函数
原型链基本不会被单独使用
问题一:原型中包含的引用值会在所有实例间共享
原型链的第二个问题是,子类型在实例化时不能给父类型的构造函数传参
盗用构造函数
为了解决原型包含引用值导致的继承问题
基本思路很简单:在子类构造函数中调用父类构造函数。
优点
相比于使用原型链,盗用构造函数的一个优点就是可以在子类构造函数中向父类构造函数传参。
缺点
盗用构造函数的主要缺点,也是使用构造函数模式自定义类型的问题
必须在构造函数中定义方法,因此函数不能重用
此外,子类也不能访问父类原型上定义的方法,因此所有类型只能使用构造函数模式
由于存在这些问题,盗用构造函数基本上也不能单独使用
组合继承
有时候也叫伪经典继承,综合了原型链和盗用构造函数,将两者的优点集中了起来
基本思路
使用原型链继承原型上的属性和方法
把方法定义在原型上以实现重用
而通过盗用构造函数继承实例属性
让每个实例都有自己的属性
存在效率问题
最主要的效率问题就是父类构造函数始终会被调用两次:
一次在是创建子类原型时调用,另一次是在子类构造函数中调用
一次在是创建子类原型时调用,另一次是在子类构造函数中调用
虽然实例属性会遮蔽原型上同名的属性
原型式继承
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
function F() {}
F.prototype = o;
return new F();
}
object()函数会创建一个临时构造函数,
将传入的对象赋值o给这个构造函数的原型,
然后返回这个临时类型的一个实例
将传入的对象赋值o给这个构造函数的原型,
然后返回这个临时类型的一个实例
适用于
你有一个对象,想在它的基础上再创建一个新对象
ECMAScript 5 通过增加 Object.create()方法将原型式继承的概念规范化
原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合。
但要记住,属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的。
但要记住,属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的。
寄生式继承
function createAnother(original){
let clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}
let clone = object(original); // 通过调用函数创建一个新对象
clone.sayHi = function() { // 以某种方式增强这个对象
console.log("hi");
};
return clone; // 返回这个对象
}
寄生式继承背后的思路类似于寄生构造函数和工厂模式:
创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象
创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象
寄生式组合继承
通过盗用构造函数继承属性,但使用混合式原型链继承方法
function inheritPrototype(subType, superType) {
let prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 赋值对象
}
let prototype = object(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 赋值对象
}
基本思路
如上的代码,不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本
寄生式组合继承可以算是引用类型继承的最佳模式
类
类定义
类构造函数
实例、原型和类成员
继承
第9章 代理与反射
代理基础
创建空代理
定义捕获器
捕获器参数和反射API
捕获器不变式
可撤销代理
实用反射API
代理另一个代理
代理的问题与不足
代理捕获器与反射方法
get()
set()
has()
defineProperty()
getOwnPropertyDescriptor()
ownKeys()
getPrototypeOf()
setPrototypeOf()
isExtensible()
preventExtensions()
construct()
代理模式
跟踪属性访问
隐藏属性
属性验证
函数与构造函数参数验证
数据绑定与可观察对象
第10章 函数
箭头函数
函数名
理解参数
没有重载
默认参数值
参数扩展与收集
扩展参数
收集参数
函数声明与函数表达式
函数作为值
函数内部
arguments
this
caller
new.target
函数属性与方法
函数表达式
递归
尾调用优化
尾调用优化的条件
尾调用优化的代码
闭包
this对象
立即调用的函数表达式
私有变量
静态私有变量
模块模式
模块增强模式
第11章 期约与异步函数
异步编程
同步与异步
以往的异步编程模式
期约(Promise)
Promises/A+规范
期约基础
期约的实例方法
期约连锁与期约合成
期约扩展
异步函数
异步函数
停止和恢复执行
异步函数策略
BOM和DOM
第12章 BOM
window对象
Global作用域
窗口关系
窗口位置与像素比
窗口大小
视口位置
导航与打开新窗口
定时器
系统对话框
location对象
查询字符串
操作地址
navigator对象
检测插件
注册处理程序
screen对象
history对象
导航
历史状态管理
第13章 客户端检测
能力检测
安全能力检测
基于能力检测进行浏览器分析
用户代理检测
用户代理的历史
浏览器分析
软件与硬件检测
识别浏览器与操作系统
浏览器元数据
硬件
第14章 DOM
节点层级
Node类型
每个节点都有 nodeType 属性
由定义在 Node 类型上的 12 个数值常量表示
Node.ELEMENT_NODE(1)
Node.ATTRIBUTE_NODE(2)
Node.TEXT_NODE(3)
Node.CDATA_SECTION_NODE(4)
Node.ENTITY_REFERENCE_NODE(5)
Node.ENTITY_NODE(6)
Node.PROCESSING_INSTRUCTION_NODE(7)
Node.COMMENT_NODE(8)
Node.DOCUMENT_NODE(9)
Node.DOCUMENT_TYPE_NODE(10)
Node.DOCUMENT_FRAGMENT_NODE(11)
Node.NOTATION_NODE(12)
nodeName和nodeValue
这两个属性的值完全取决于节点类型。在使用这两个属性前,最好先检测节点类型
对元素类型而言,nodeName 始终等于元素的标签名,而 nodeValue 则始终为 null。
节点关系
文档树
每个节点都有一个 childNodes 属性,其中包含一个 NodeList 的实例
NodeList 是一个类数组对象,用于存储可以按位置存取的有序节点
NodeList 并不是 Array 的实例,但可以使用中括号访问它的值,而且它也有 length 属性
NodeList 是实时的活动对象,而不是第一次访问时所获得内容的快照
NodeList 对象独特的地方在于,
它其实是一个对 DOM 结构的查询,因此 DOM 结构的变化会自动地在 NodeList 中反映出来。
它其实是一个对 DOM 结构的查询,因此 DOM 结构的变化会自动地在 NodeList 中反映出来。
每个节点都有一个 parentNode 属性,指向其 DOM 树中的父元素。
父节点和它的第一个及最后一个子节点也有专门属性:
firstChild 和 lastChild 分别指向childNodes 中的第一个和最后一个子节点。
firstChild 和 lastChild 分别指向childNodes 中的第一个和最后一个子节点。
最后还有一个所有节点都共享的关系
ownerDocument 属性是一个指向代表整个文档的文档节点的指针
操纵节点
appendChild(),用于在 childNodes 列表末尾添加节点
添加新节点会更新相关的关系指针,包括父节点和之前的最后一个子节点。
如果把文档中已经存在的节点传给 appendChild(),则这个节点会从之前的位置被转移到新位置。
如果想把节点放到 childNodes 中的特定位置而不是末尾,则可以使用 insertBefore()方法。
接收两个参数:要插入的节点和参照节点
// 作为最后一个子节点插入
returnedNode = someNode.insertBefore(newNode, null);
returnedNode = someNode.insertBefore(newNode, null);
// 作为新的第一个子节点插入
returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); // true
alert(newNode == someNode.firstChild); // true
returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); // true
alert(newNode == someNode.firstChild); // true
// 插入最后一个子节点前面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length - 2]); // true
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length - 2]); // true
appendChild() 和 insertBefore() 在插入节点时不会删除任何已有节点。
replaceChild()方法替换节点
法接收两个参数:要插入的节点和要替换的节点
要替换的节点会被返回并从文档树中完全移除,要插入的节点会取而代之。
// 替换第一个子节点
let returnedNode = someNode.replaceChild(newNode, someNode.firstChild);
let returnedNode = someNode.replaceChild(newNode, someNode.firstChild);
// 替换最后一个子节点
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
虽然被替换的节点从技术上说仍然被同一个文档所拥有,但文档中已经没有它的位置。
要移除节点而不是替换节点,可以使用 removeChild()方法
这个方法接收一个参数,即要移除的节点。
被移除的节点会被返回
被移除的节点会被返回
// 删除第一个子节点
let formerFirstChild = someNode.removeChild(someNode.firstChild);
let formerFirstChild = someNode.removeChild(someNode.firstChild);
// 删除最后一个子节点
let formerLastChild = someNode.removeChild(someNode.lastChild);
let formerLastChild = someNode.removeChild(someNode.lastChild);
与 replaceChild()方法一样,通过 removeChild()被移除的节点从技术上说
仍然被同一个文档所拥有,但文档中已经没有它的位置。
仍然被同一个文档所拥有,但文档中已经没有它的位置。
上面介绍的 4 个方法都用于操纵某个节点的子元素,
也就是说使用它们之前必须先取得父节点(使用前面介绍的 parentNode 属性)。
也就是说使用它们之前必须先取得父节点(使用前面介绍的 parentNode 属性)。
并非所有节点类型都有子节点,
如果在不支持子节点的节点上调用这些方法,则会导致抛出错误。
如果在不支持子节点的节点上调用这些方法,则会导致抛出错误。
其他方法
cloneNode()
返回与调用它的节点一模一样的节点
接收一个布尔值参数,表示是否深复制
在传入 true 参数时,会进行深复制,即复制节点及其整个子 DOM 树
传入 false,则只会复制调用该方法的节点
复制返回的节点属于文档所有,但尚未指定父节点,所以可称为孤儿节点(orphan)
这个方法只复制 HTML 属性,以及可选地复制子节点
不会复制添加到 DOM 节点的 JavaScript 属性,比如事件处理程序。
normalize()
处理文档子树中的文本节点
文本节点归一化
在节点上调用 normalize()方法会检测这个节点的所有后代,
从中搜索上述两种情形
从中搜索上述两种情形
并不包含文本的文本节点
文本节点之间互为同胞关系
作用
如果发现空文本节点,则将其删除
如果两个同胞节点是相邻的,则将其合并为一个文本节点
Document类型
表示文档节点的类型
浏览器中,文档对象 document 是HTMLDocument 的实例(HTMLDocument 继承 Document),表示整个 HTML 页面
document 是 window对象的属性,因此是一个全局对象
Document 类型的节点有以下特征
nodeType 等于 9;
nodeName 值为"#document";
nodeValue 值为 null;
parentNode 值为 null;
ownerDocument 值为 null;
子节点可以是
DocumentType(最多一个)
Element(最多一个)
ProcessingInstruction
Comment 类型
document 对象可用于获取关于页面的信息以及操纵其外观和底层结构
文档子节点
子节点可以是 DocumentType、Element、ProcessingInstruction 或 Comment
两个访问子节点的快捷方式
document 对象的documentElement 属性,始终指向 HTML 页面中的<html>元素
作为 HTMLDocument 的实例,document 对象还有一个 body 属性,直接指向<body>元素
Document 类型另一种可能的子节点是 DocumentType
<!doctype>标签是文档中独立的部分,其信息可以通过 doctype 属性(在浏览器中是 document.doctype)来访问
一般来说,appendChild()、removeChild()和 replaceChild()方法不会用在 document 对象上。
这是因为文档类型(如果存在)是只读的,而且只能有一个 Element 类型的子节点(即<html>,已经存在了)。
这是因为文档类型(如果存在)是只读的,而且只能有一个 Element 类型的子节点(即<html>,已经存在了)。
文档信息
title属性
包含<title>元素中的文本,通常显示在浏览器窗口或标签页的标题栏
通过这个属性可以读写页面的标题,修改后的标题也会反映在浏览器标题栏上。
不过,修改 title 属性并不会改变<title>元素。
不过,修改 title 属性并不会改变<title>元素。
let originalTitle = document.title;
// 修改文档标题
document.title = "New page title";
// 修改文档标题
document.title = "New page title";
URL属性
URL 包含当前页面的完整 URL(地址栏中的 URL)
// 取得完整的 URL
let url = document.URL;
let url = document.URL;
domain属性
domain 包含页面的域名
// 取得域名
let domain = document.domain;
let domain = document.domain;
referrer属性
referrer 包含链接到当前页面的那个页面的 URL(转跳前的url)
// 取得来源
let referrer = document.referrer;
let referrer = document.referrer;
在这些属性中,只有 domain 属性是可以设置的
出于安全考虑,给 domain 属性设置的值是有限制的
不能给这个属性设置 URL 中不包含的值
当页面中包含来自某个不同子域的窗格(<frame>)或内嵌窗格(<iframe>)时,
设置document.domain 是有用的
设置document.domain 是有用的
因为跨源通信存在安全隐患,所以不同子域的页面间无法通过 JavaScript通信。
此时,在每个页面上把 document.domain 设置为相同的值,这些页面就可以访问对方的 JavaScript对象了。
此时,在每个页面上把 document.domain 设置为相同的值,这些页面就可以访问对方的 JavaScript对象了。
定位元素
getElementById()
接收一个参数,即要获取元素的 ID
参数 ID 必须跟元素在页面中的 id 属性值完全匹配,包括大小写
如果找到了则返回这个元素,如果没找到则返回 null
如果页面中存在多个具有相同 ID 的元素,则 getElementById()返回在文档中出现的第一个元素
所以尽量保持id的唯一性
getElementsByTagName()
接收一个参数,即要获取元素的标签名
返回包含零个或多个元素的 NodeList
在 HTML 文档中,这个方法返回一个HTMLCollection 对象
与NodeList对象一样,也可以
使用中括号或item()方法从HTMLCollection取得特定的元素
使用中括号或item()方法从HTMLCollection取得特定的元素
let images = document.getElementsByTagName("img");
alert(images.length); // 图片数量
alert(images[0].src); // 第一张图片的 src 属性
alert(images.item(0).src); // 同上
alert(images.length); // 图片数量
alert(images[0].src); // 第一张图片的 src 属性
alert(images.item(0).src); // 同上
还有一个额外的方法 namedItem(),
可通过标签的 name 属性取得某一项的引用
可通过标签的 name 属性取得某一项的引用
例如,假设页面中包含如下的<img>元素:
<img src="myimage.gif" name="myImage">
那么也可以像这样从 images 中取得对这个<img>元素的引用:
let myImage = images.namedItem("myImage");
<img src="myimage.gif" name="myImage">
那么也可以像这样从 images 中取得对这个<img>元素的引用:
let myImage = images.namedItem("myImage");
对于 name 属性的元素,还可以直接使用中括号来获取,如下面的例子所示:
let myImage = images["myImage"];
let myImage = images["myImage"];
要取得文档中的所有元素,可以给 getElementsByTagName()传入*
let allElements = document.getElementsByTagName("*");
let allElements = document.getElementsByTagName("*");
返回包含页面中所有元素的 HTMLCollection 对象,
顺序就是它们在页面中出现的顺序
顺序就是它们在页面中出现的顺序
getElementsByName()
这个方法会返回具有给定 name 属性的所有元素
getElementsByName()方法最常用于单选按钮,
因为同一字段的单选按钮必须具有相同的 name 属性才能确保把正确的值发送给服务器
因为同一字段的单选按钮必须具有相同的 name 属性才能确保把正确的值发送给服务器
与 getElementsByTagName()一样,getElementsByName()方法也返回 HTMLCollection。
不过在这种情况下,namedItem()方法只会取得第一项(因为所有项的 name 属性都一样)。
不过在这种情况下,namedItem()方法只会取得第一项(因为所有项的 name 属性都一样)。
特殊集合
document 对象上还暴露了几个特殊集合,这些集合也都是 HTMLCollection 的实例
document.anchors 包含文档中所有带 name 属性的<a>元素
document.links 包含文档中所有带 href 属性的<a>元素
document.applets 包含文档中所有<applet>元素(因为<applet>元素已经不建议使用,所以这个集合已经废弃)
document.forms 包含文档中所有<form>元素(与 document.getElementsByTagName ("form")返回的结果相同)
document.images 包含文档中所有<img>元素(与 document.getElementsByTagName ("img")返回的结果相同)
DOM 兼容性检测
由于 DOM 有多个 Level 和多个部分,因此确定浏览器实现了 DOM 的哪些部分是很必要的。
document.implementation 属性是一个对象,其中提供了与浏览器 DOM 实现相关的信息和能力。
document.implementation 属性是一个对象,其中提供了与浏览器 DOM 实现相关的信息和能力。
文档写入
document 对象有一个古老的能力,即向网页输出流中写入内容。
这个能力对应 4 个方法:
write()、writeln()、open()和 close()
这个能力对应 4 个方法:
write()、writeln()、open()和 close()
write()和 writeln()方法都接收一个字符串参数,可以将这个字符串写入网页中。
write()简单地写入文本,而 writeln()还会在字符串末尾追加一个换行符(\n)。
write()简单地写入文本,而 writeln()还会在字符串末尾追加一个换行符(\n)。
write()和 writeln()方法经常用于动态包含外部资源,如 JavaScript 文件
在包含 JavaScript 文件时,记住不能像直接包含字符串"</script>",
因为这个字符串会被解释为脚本块的结尾,导致后面的代码不能执行
要修改成"<\/script>"
因为这个字符串会被解释为脚本块的结尾,导致后面的代码不能执行
要修改成"<\/script>"
如果是在页面加载完之后再调用 document.write(),
则输出的内容会重写整个页面
则输出的内容会重写整个页面
open()和 close()方法分别用于打开和关闭网页输出流。
在调用 write()和 writeln()时,这两个方法都不是必需的。
在调用 write()和 writeln()时,这两个方法都不是必需的。
Element类型
Text类型
Comment类型
CDATASection类型
DocumentType类型
DocumentFragment类型
Attr类型
DOM编程
动态脚本
动态样式
操作表格
使用NodeList
MutationObserver接口
基本用法
MutationObserverInit与观察范围
异步回调与记录队列
性能、内存与垃圾回收
第15章 DOM扩展
Selectors API
querySelector()
querySelectorAll()
matches()
元素遍历
HTML5
CSS类扩展
焦点管理
HTMLDocument扩展
字符集属性
自定义数据属性
插入标记
scrollIntoView()
专有扩展
children属性
contains()方法
插入标记
滚动
第16章 DOM2和DOM3
DOM的演进
XML命名空间
其他变化
样式
存取元素样式
操作样式表
元素尺寸
遍历
NodeIterator
TreeWalker
范围
DOM范围
简单选择
复杂选择
操作范围
范围插入
范围折叠
范围比较
复制范围
清理
第17章 事件
事件流
事件冒泡
事件捕获
DOM事件流
事件处理程序
HTML事件处理程序
DOM0事件处理程序
DOM2事件处理程序
IE事件处理程序
跨浏览器事件处理程序
事件对象
DOM事件对象
IE事件对象
跨浏览器事件对象
事件类型
用户界面事件
焦点事件
鼠标和滚轮事件
键盘和输入事件
合成事件
变化事件
HTML5事件
设备事件
触摸及手势事件
事件参考
内存与性能
事件委托
删除事件处理程序
模拟事件
DOM事件模拟
IE事件模拟
第18章 动画与Canvas图形
使用requestAnimationFrame
早期定时动画
时间间隔的问题
requestAnimationFrame
cancelAnimationFrame
通过requestAnimationFrame节流
基本的画布功能
2D绘图上下文
填充和描边
绘制矩形
绘制文本
变换
绘制图像
阴影
渐变
图案
图像数据
合成
WebGL
WebGL上下文
WebGL基础
WebGL1与WebGL2
第19章 表单脚本
表单基础
提交表单
重置表单
表单字段
文本框编程
选择文本
输入过滤
自动切换
HTML5约束验证API
选择框编程
选项处理
添加选项
移除选项
移动和重排选项
表单序列化
富文本编辑
使用contenteditable
与富文本交互
富文件选择
通过表单提交富文本
Javascript API
第20章 JavaScript API
Atomics与SharedArrayBuffer
SharedArrayBuffer
原子操作基础
跨上下文消息
Encoding API
文本编码
文本解码
File API与Blob API
File类型
FileReader类型
FileReaderSync类型
Blob与部分读取
对象URL与Blob
读取拖放文件
媒体元素
属性
事件
检测编解码器
音频类型
原生拖放
拖放事件
自定义放置目标
dataTransfer对象
dropEffect与effectAllwed
可拖动能力
其他成员
Notifications API
通知权限
显示和隐藏通知
通知生命周期回调
Page Visibility API
Streams API
理解流
可读流
可写流
转换流
通过管道连接流
计时API
High Resolution Time API
Performance Timeline API
Web组件
HTML模板
影子DOM
自定义元素
Web Cryptography API
生成随机数
使用SubtleCrypto对象
第21章 错误处理与调试
浏览器错误报告
桌面控制台
移动控制台
错误处理
try/catch语句
抛出错误
error事件
错误处理策略
识别错误
区分重大与非重大错误
把错误记录到服务器中
调试技术
把消息记录到控制台
理解控制台运行时
使用JavaScript调试器
在页面中打印消息
补充控制台方法
抛出错误
旧版本IE常见错误
无效字符
未找到成员
未知运行时错误
语法错误
系统找不到指定资源
第22章 处理XML
浏览器对XML DOM的支持
DOM Level 2 Core
DOMParser类型
XMLSerializer类型
浏览器对XPath的支持
DOM Level 3 XPath
单个节点结果
简单类型结果
默认类型结果
命名空间支持
浏览器对XSLT的支持
XSLTProcessor类型
使用参数
重置处理器
第23章 JSON
语法
简单值
对象
数组
解析与序列化
JSON对象
序列化选项
解析选项
第24章 网络请求与远程资源
XMLHttpRequest对象
使用XHR
HTTP头部
GET请求
POST请求
XMLHttpRequest Level 2
进度事件
load事件
progress事件
跨源资源共享
预检请求
凭据请求
替代性跨源技术
图片探测
JSONP
Fetch API
基本用法
常见Fetch请求模式
Header对象
Request对象
Response对象
Request、Response及Body混入
Beacon API
Web Socket
API
发送和接收数据
其他事件
安全
第25章 客户端存储
cookie
限制
cookie的构成
JavaScript中的cookie
子cookie
使用cookie的注意事项
Web Storage
Storage类型
sessionStorage对象
localStorage对象
存储事件
限制
IndexedDB
数据库
对象存储
事务
插入对象
通过游标查询
键范围
设置游标方向
索引
并发问题
限制
第26章 模块
理解模块模式
模块标识符
模块依赖
模块加载
入口
异步依赖
动态依赖
静态分析
循环依赖
凑合的模块系统
使用ES6之前的模块加载器
CommonJS
异步模块定义
通用模块定义
模块加载器终将没落
使用ES6模块
模块标签及定义
模块加载
模块行为
模块导出
模块导入
模块转移导出
工作者模块
向后兼容
第27章 工作者线程
工作者线程简介
工作者线程与线程
工作者线程的类型
WorkerGlobalScope
专用工作者线程
专用工作者线程的基本概念
专用工作者线程与隐式MessagePorts
专用工作者线程的生命周期
配置Worker选项
在JavaScript行内创建工作者线程
在工作者线程中动态执行脚本
委托任务到子工作者线程
处理工作者线程错误
与专用工作者线程通信
工作者线程数据传输
线程池
共享工作者线程
共享工作者线程简介
理解共享工作者线程的生命周期
连接到共享工作者线程
服务工作者线程
服务工作者线程基础
服务工作者线程缓存
服务工作者线程客户端
服务工作者线程与一致性
理解服务工作者线程的生命周期
控制反转与服务工作者线程持久化
通过updateVIaCache管理服务文件缓存
强制性服务工作者线程操作
服务工作者线程消息
拦截fetch事件
推送通知
JavaScript设计模式和实践策略
第28章 最佳实践
可维护性
什么是可维护的代码
编码规范
松散耦合
编码惯例
性能
作用域意识
选择正确的方法
语句最少化
优化DOM交互
部署
构建流程
验证
压缩
0 条评论
下一页