学习笔记 2020-11-11
JavaScript 高级程序设计(第4版) 阅读记录
DOM 拓展
Selectors API
Selectors API 是 W3C 推荐标准,规定了浏览器原生支持的 CSS 查询API 。
核心是两个方法,querySelector() 和 querySelectorAll() 。在兼容浏览器中,Document 类型和 Element 类型的实例上都会暴露这两个方法。
querySelector()
该方法接收 CSS 选择符参数,返回匹配该模式的第一个后代元素或 null 。
querySelectorAll()
该方法也接收一个用于查询的参数,但它会返回所有匹配的节点。该方法返回一个 NodeList 的静态实例。
matches()
该方法接收一个 CSS 选择符参数,如果元素匹配则该选择符返回 true ,否则返回 false 。
元素遍历
IE9 之前的版本不会把元素间的空格当成空白节点,而其他浏览器会。这样导致了 childNodes 和 firstChild 等属性上的差异。为了弥补这个差异,同时不影响 DOM 规范, W3C 通过新的 Element Traversal 规范定义了一组新属性。
- childElementCount,返回子元素数量 ( 不包含文本节点和注释 );
- firstElementChild,指向第一个 Element 类型的子元素;
- lastElementChild;
- previousElementSibling,指向前一个 Element 类型的同胞元素;
- nextElementSibling;
HTML5
HTML5 规范包含了与标记相关的大量 JavaScript API 定义。
CSS 类拓展
getElementsByClassName()
该方法暴露在 document 对象和所有 HTML 元素上。返回包含相应类的元素的 NodeList 。
IE9 及以上版本,以及所有现代浏览器都支持该方法。
classList 属性
可以通过 className 属性操作类名,但该属性是一个字符串。
classList 是一个新的集合类型 DOMTokenList 的实例。该类型也有 length 属性表示自己包含多少项,可以通过 item() 或中括号取得个别的元素。还有一些方法:
- add(value);
- contains(value),返回布尔值,表示给定的 value 是否存在;
- remove(value);
- toggle(value),若已存在则删除,不存在则添加。
IE10 及以上版本和其他主流浏览器实现了该属性。
焦点管理
HTML5 添加了辅助 DOM 焦点管理的功能。
document.activeElement
始终包含当前拥有焦点的 DOM 元素。
默认情况下,该属性会在页面刚加载完之后设置为 document.body 。在那之前,值为 null 。
document.hasFocus()
返回布尔值,表示文档是否拥有焦点。
HTMLDocument 拓展
readyState
该属性最早是 IE4 添加到 document 对象上。HTML5将这个属性写入了标准。该属性有两个值:
- loading,表示文档正在加载;
- complete,表示文档加载完成。
compatMode 属性
自从 IE6 提供了以标准或混杂模式渲染页面的能力之后,检测页面渲染模式成为一个必要的需求。这个属性指示浏览器当前处于什么渲染模式下。
标准模式下,这个属性的值是 “CSS1Compat”,而在混杂模式下,值是 “BackCompat”。
head 属性
该属性指向文档的
<head>属性。
字符集属性
characterSet 属性表示文档实际使用的字符集,也可以用来指定新字符集。
自定义数据属性
浏览器允许给元素指定非标准的属性,最好以前缀 data- 来指定。
自定义属性可以通过元素的 dataset 属性来访问。dataset 属性是一个 DOMStringMap 的实例,包含一组键/值对映射。元素的每个 data-name 属性在 dataset 中都可以通过 data- 后面的字符串作为键来访问。
插入标记
innerHTML
在读取 innerHTML 属性时,会返回元素所有后代的 HTML 字符串,包括元素、注释和文本节点。在写入时,会根据提供的字符串值以新的 DOM 子树替代元素中原来包含的所有子节点。
旧 IE中的 innerHTML
在所有现代浏览器中,通过 innerHTML 插入的
<script>标签是不会执行的。而在 IE8 及之前的版本中,只要这样插入的<script>元素指定了 defer 属性,且<script>之前是 受控元素,那就是可以执行的。<script>元素与<style>或注释一样,都是非受控元素,也就是在页面上看不到它们。IE 会把 innerHTML 中从非受控元素开始的内容都删掉。outerHTML 属性
读取 outerHTML 属性时,会返回调用它的元素及所有后代元素的 HTML 字符串。在写入 outerHTML 属性时,调用它的元素会被传入的 HTML 字符串经解释之后生成的 DOM 子树取代。
insertAdjacentHTML() 与 insertAdjacentText()
这两个方法最早源自 IE ,接收两个参数,要插入标记的位置和要插入的 HTML 或文本。
第一个参数必须是下列值的一个:
- beforebegin,插入当前元素前面,作为前一个同胞节点;
- afterbegin,插入当前元素内部,作为新的子节点或放在第一个子节点后面;
- beforeend,插入当前元素内部,作为新的子节点或放在最后一个子节点后面;
- afterend,插入当前元素后面;
以上值不区分大小写。
现代 JavaScript 教程
JSON方法,toJSON
排除和转换:replacer
JSON.stringify 的完整语法是:
let json = JSON.stringify(value, replacer?, space?);
- value,要编码的值。
- replacer,要编码的属性数组或映射函数
function(key, value)。 - space,用于格式化的空格数量。
let room = {
number: 23
};
let meetup = {
title: 'Conference',
participants: [{ name: 'John' }, { name: 'Alice' }],
place: room // meetup 引用了 room
};
room.occupiedBy = meetup; // room 引用了 meetup
console.log(JSON.stringify(meetup, ['title', 'participants']));
// {"title":"Conference","participants":[{},{}]}
let room = {
number: 23
};
let meetup = {
title: 'Conference',
participants: [{ name: 'John' }, { name: 'Alice' }],
place: room // meetup 引用了 room
};
room.occupiedBy = meetup; // room 引用了 meetup
console.log(
JSON.stringify(meetup, function replacer(key, value) {
console.log(`${key}: ${value}`);
return key == 'occupiedBy' ? undefined : value;
})
);
/* key:value pairs that come to replacer:
: [object Object]
title: Conference
participants: [object Object],[object Object]
0: [object Object]
name: John
1: [object Object]
name: Alice
place: [object Object]
number: 23
*/
格式化:space
第三个参数用于优化格式的空格数量。
自定义 “toJSON”
可以给对象自定义 toJSON 方法来自定义 JSON 转换。
JSON.parse
let value = JSON.parse(str, reviver?);
- str,要解析的 JSON 字符串。
- reviver,可选的函数
function(key, value),该函数将为每个键值对调用。
例子,JSON 对象中的日期值 parse 之后依然是一个字符串,可以提供 reviver 函数来进行转换。
任务
将对象转换为 JSON,然后再转换回来
将
user转换为 JSON,然后将其转换回到另一个变量。let user = { name: "John Smith", age: 35 };let str = JSON.stringify(user); let obj = JSON.parse(str);排除反向引用
在简单循环引用的情况下,我们可以通过名称排除序列化中违规的属性。
但是,有时我们不能只使用名称,因为它既可能在循环引用中也可能在常规属性中使用。因此,我们可以通过属性值来检查属性。
编写
replacer函数,移除引用meetup的属性,并将其他所有属性序列化:let room = { number: 23 }; let meetup = { title: "Conference", occupiedBy: [{name: "John"}, {name: "Alice"}], place: room }; // 循环引用 room.occupiedBy = meetup; meetup.self = meetup; alert( JSON.stringify(meetup, function replacer(key, value) { /* your code */ })); /* 结果应该是: { "title":"Conference", "occupiedBy":[{"name":"John"},{"name":"Alice"}], "place":{"number":23} } */console.log( JSON.stringify(meetup, function replacer(key, value) { if (value === meetup && key !== '') { console.log(this); return undefined; } else { return value; } }) );