0%

学习笔记 2020 11 08

学习笔记 2020-11-08

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

DOM

节点层级

Element 类型
  1. HTML 元素

    所有 HTML 元素都通过 HTMLElement 类型表示。 HTMLElement 直接继承 Element 并增加了一些属性。每个属性对应以下属性之一,它们是所有 HTML 元素上都有的标准属性:

    • id:元素在文档中的唯一标识符。
    • title:包含元素的额外信息,通常以提示条形式展示。
    • lang:元素内容的语言代码。
    • dir:元素的书写方向 ( “ltr” 表示从左到右,“rtl”表示从右到左。 )
    • className:元素的 CSS 类。

    这些属性可以获取对应的值,也可以用来修改相应的值。

    所有 HTML 元素都是 HTMLElement 或其子类型的实例。

    下表是所有 HTML 元素以及对应的类型,( 斜体表示已经废弃的元素 )。

    image-20201108085455515

    image-20201108085523831

  2. 取得属性

    每个元素都有零个或多个属性。与属性相关的 DOM 方法有三个:

    • getAttribute()
    • setAttribute()
    • removeAttribute()

    getAttribute() 能取得正式属性和自定义属性。属性名不区分大小写。根据 HTML5 规范的要求,自定义属性名应该前缀 data- 以方便验证。

    元素的所有属性都可以通过 DOM 元素对象的属性来取得,除了自定义属性。

    通过 DOM 元素对象访问的属性有两个返回的值跟使用 getAttribute() 取得的值不一样。首先是 style 属性。在使用 getAttribute() 访问 style 属性时,返回的是 CSS 字符串。而在通过 DOM 对象的属性访问时, style 属性返回的是一个 ( CSSStyleDeclaration ) 对象。DOM 对象的 style 属性用于以编程方式读写元素样式,因此不会直接映射为元素中 style 属性的字符串值。(存疑,验证了一下 style 属性会返回 DOM 对象 style 属性的修改。)

    第二类是事件处理程序。在 DOM 元素上获取事件属性,得到 JS 代码。使用 getAttribute() 访问,得到字符串形式的源码。( 存疑,验证了以下使用 getAttribute() 获取的是 null 。)

  3. 设置属性

    setAttribute() 接收两个参数,要设置的属性名和属性的值。适用于 HTML 属性和自定义属性。在 DOM 对象上添加自定义属性,不会自动变成元素的属性。

  4. attributes 属性

    Element 类型是唯一使用 attributes 属性的 DOM 节点类型。attributes 属性包含一个 NamedNodeMap 实例,是一个类似 NodeList 的实时集合。元素的每个属性都表示为一个 Attr 节点,并保存在这个 NamedNodeMap 对象中。NamedNodeMap 对象包含下列方法:

    • getNamedItem(name),返回 nodeName 属性等于 name 的节点;
    • removeNamedItem(name),删除 nodeName 属性等于 name 的节点;
    • setNamedItem(node),向列表中添加 node 节点,以其 nodeName 为索引;
    • item(pos),返回索引位置 pos 处的节点。

    attributes 属性中的每个节点的 nodeName 是对应属性的名字,nodeValue 是属性的值。

    attributes 属性最有用的场景是需要迭代元素上所有属性的时候。

  5. 创建元素

    使用 document.createElement() 方法创建新元素,接受一个参数,即要创建元素的标签名。HTML 文档中,标签名不区分大小写。

    使用该方法创建新元素的同时也会将其 ownerDocument 属性设置为 document。

  6. 元素后代

    元素可以拥有任意多个子元素和后代元素。

Text 类型

Text 节点由 Text 类型表示,包含按字面解释的纯文本,也可能包含转移后的 HTML 字符。Text 类型的节点具有以下特征:

  • nodeType 等于 3;
  • nodeName 值为 “#text”;
  • nodeValue 值为节点中包含的文本;
  • parentNode 值为 Element 对象;
  • 不支持子节点。

Text 节点中包含的文本可以通过 nodeValue 属性访问,也可以通过 data 属性访问。文本节点暴露了以下操作文本的方法:

  • appendData(text),向节点末尾添加文本 text;
  • deleteData(offset, count),从位置 offset 开始删除 count 个字符;
  • insertData(offset, text),在位置 offset 插入 text;
  • replaceData(offset, count, text),用 text 替换从位置 offset 到 offset + count 的文本;
  • splitText(offset),在位置 offset 将当前文本节点拆分为两个文本节点;
  • substringData(offset, count),提取从位置 offset 到 offset + count 的文本。

还可以通过 length 属性获取文本节点中包含的字符数量。这个值等于 nodeValue.length 和 data.length 。

  1. 创建文本节点

    document.createTextNode() 可以用来创建新文本节点,接收一个参数,即要插入节点的文本。

  2. 规范化文本节点

    normalize() 方法用于合并相邻的文本节点,是在 Node 类型中定义的。在父节点上调用时,所有同胞文本节点会被合并为一个文本节点。

  3. 拆分文本节点

    Text 类型定义了一个与 normalize() 相反的方法—— splitText() 。这个方法可以在指定的偏移位置拆分 nodeValue 。

Comment 类型

DOM 中的注释通过 Comment 类型表示,具有以下特征:

  • nodeType 等于 8 ;
  • nodeName 值为 “#comment”;
  • nodeValue 值为注释的内容;
  • parentNode 值为 Document 或 Element 对象;
  • 不支持子节点。

Comment 类型与 Text 类型继承同一个基类 ( CharacterData ) ,因此拥有除 splitText() 之外 Text 节点所有的字符串操作方法。

可以使用 documen.createCommment() 方法创建注释节点,参数为注释文本。

CDATASection 类型

CDATASection 类型表示 XML 中特有的 CDATA 区块。CDATASection 类型继承 Text 类型,因此拥有包括 splitText() 在内的所有字符串操作方法。CDATASection 类型的节点具有以下特性:

  • nodeType 等于 4 ;
  • nodeName 值为 “#cdata-section”;
  • nodeValue 值为 CDATA 区块的内容;
  • parentNode 值为 Document 或 Element 对象;
  • 不支持子节点。

CDATA 区块只有 XML 文档中有效。可以使用 document.createCDataSection() 并传入节点内容来创建 CDATA 区块。

DocumentType 类型

DocumentType 类型的节点包含文档的文档类型信息,具有以下特征:

  • nodeType 等于 10 ;
  • nodeName 值为文档类型的名称;
  • nodeValue 值为 null ;
  • parentNode 值为 Document 对象;
  • 不支持子节点。

DocumentType 对象在 DOM Level 1 中不支持动态创建,只能在解析文档代码时创建。对于支持这个类型的浏览器, DocumentType 对象保存在 document.doctype 属性中。DOM Level 1 规定了 DocumentType 对象的 3 个属性: name 、 entities 和 notations 。其中, name 是文档类型的名称, entities 是这个文档类型描述的实体的 NamedNodeMap ,而 notations 是这个文档类型描述的表示法的 NamedNodeMap 。因为浏览器中的文档通常是 HTML 和 XHTML 文档类型,所以 entities 和 notations 列表为空。

现代 JavaScript 教程

任务

  1. 属性求和

    有一个带有任意数量薪水的 salaries 对象。

    编写函数 sumSalaries(salaries),该函数使用 Object.valuesfor..of 循环返回所有薪水的总和。

    如果 salaries 是空对象,那么结果必须是 0

    举个例子:

    let salaries = {
      "John": 100,
      "Pete": 300,
      "Mary": 250
    };
    
    alert( sumSalaries(salaries) ); // 650
    function sumSalaries(arr) {
      const values = Object.values(arr);
      let sum = 0;
      for (let value of values) {
        sum += value;
      }
      return sum;
    }
  2. 计算属性数量

    写一个函数 count(obj),该函数返回对象中的属性的数量:

    let user = {
      name: 'John',
      age: 30
    };
    
    alert( count(user) ); // 2

    试着使代码尽可能简短。

    P.S. 忽略 Symbol 类型属性,只计算“常规”属性。

    function count(user) {
      return Object.keys(user).length;
    }