0%

学习笔记 2020 11 11

学习笔记 2020-11-11

JavaScript 高级程序设计(第4版) 阅读记录

DOM 拓展

Selectors API

Selectors API 是 W3C 推荐标准,规定了浏览器原生支持的 CSS 查询API 。

核心是两个方法,querySelector() 和 querySelectorAll() 。在兼容浏览器中,Document 类型和 Element 类型的实例上都会暴露这两个方法。

  1. querySelector()

    该方法接收 CSS 选择符参数,返回匹配该模式的第一个后代元素或 null 。

  2. querySelectorAll()

    该方法也接收一个用于查询的参数,但它会返回所有匹配的节点。该方法返回一个 NodeList 的静态实例。

  3. matches()

    该方法接收一个 CSS 选择符参数,如果元素匹配则该选择符返回 true ,否则返回 false 。

元素遍历

IE9 之前的版本不会把元素间的空格当成空白节点,而其他浏览器会。这样导致了 childNodes 和 firstChild 等属性上的差异。为了弥补这个差异,同时不影响 DOM 规范, W3C 通过新的 Element Traversal 规范定义了一组新属性。

  • childElementCount,返回子元素数量 ( 不包含文本节点和注释 );
  • firstElementChild,指向第一个 Element 类型的子元素;
  • lastElementChild;
  • previousElementSibling,指向前一个 Element 类型的同胞元素;
  • nextElementSibling;

HTML5

HTML5 规范包含了与标记相关的大量 JavaScript API 定义。

CSS 类拓展
  1. getElementsByClassName()

    该方法暴露在 document 对象和所有 HTML 元素上。返回包含相应类的元素的 NodeList 。

    IE9 及以上版本,以及所有现代浏览器都支持该方法。

  2. classList 属性

    可以通过 className 属性操作类名,但该属性是一个字符串。

    classList 是一个新的集合类型 DOMTokenList 的实例。该类型也有 length 属性表示自己包含多少项,可以通过 item() 或中括号取得个别的元素。还有一些方法:

    • add(value);
    • contains(value),返回布尔值,表示给定的 value 是否存在;
    • remove(value);
    • toggle(value),若已存在则删除,不存在则添加。

    IE10 及以上版本和其他主流浏览器实现了该属性。

焦点管理

HTML5 添加了辅助 DOM 焦点管理的功能。

  1. document.activeElement

    始终包含当前拥有焦点的 DOM 元素。

    默认情况下,该属性会在页面刚加载完之后设置为 document.body 。在那之前,值为 null 。

  2. document.hasFocus()

    返回布尔值,表示文档是否拥有焦点。

HTMLDocument 拓展
  1. readyState

    该属性最早是 IE4 添加到 document 对象上。HTML5将这个属性写入了标准。该属性有两个值:

    • loading,表示文档正在加载;
    • complete,表示文档加载完成。
  2. compatMode 属性

    自从 IE6 提供了以标准或混杂模式渲染页面的能力之后,检测页面渲染模式成为一个必要的需求。这个属性指示浏览器当前处于什么渲染模式下。

    标准模式下,这个属性的值是 “CSS1Compat”,而在混杂模式下,值是 “BackCompat”。

  3. head 属性

    该属性指向文档的 <head> 属性。

字符集属性

characterSet 属性表示文档实际使用的字符集,也可以用来指定新字符集。

自定义数据属性

浏览器允许给元素指定非标准的属性,最好以前缀 data- 来指定。

自定义属性可以通过元素的 dataset 属性来访问。dataset 属性是一个 DOMStringMap 的实例,包含一组键/值对映射。元素的每个 data-name 属性在 dataset 中都可以通过 data- 后面的字符串作为键来访问。

插入标记
  1. innerHTML

    在读取 innerHTML 属性时,会返回元素所有后代的 HTML 字符串,包括元素、注释和文本节点。在写入时,会根据提供的字符串值以新的 DOM 子树替代元素中原来包含的所有子节点。

  2. 旧 IE中的 innerHTML

    在所有现代浏览器中,通过 innerHTML 插入的 <script> 标签是不会执行的。而在 IE8 及之前的版本中,只要这样插入的 <script> 元素指定了 defer 属性,且 <script> 之前是 受控元素,那就是可以执行的。<script> 元素与 <style> 或注释一样,都是非受控元素,也就是在页面上看不到它们。IE 会把 innerHTML 中从非受控元素开始的内容都删掉。

  3. outerHTML 属性

    读取 outerHTML 属性时,会返回调用它的元素及所有后代元素的 HTML 字符串。在写入 outerHTML 属性时,调用它的元素会被传入的 HTML 字符串经解释之后生成的 DOM 子树取代。

  4. 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 函数来进行转换。

任务

  1. 将对象转换为 JSON,然后再转换回来

    user 转换为 JSON,然后将其转换回到另一个变量。

    let user = {
      name: "John Smith",
      age: 35
    };
    let str = JSON.stringify(user);
    let obj = JSON.parse(str);
  2. 排除反向引用

    在简单循环引用的情况下,我们可以通过名称排除序列化中违规的属性。

    但是,有时我们不能只使用名称,因为它既可能在循环引用中也可能在常规属性中使用。因此,我们可以通过属性值来检查属性。

    编写 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;
        }
      })
    );