2025-02-18 日报 Day101

2025-02-18 日报 Day101

Yuyang 前端小白🥬

今日的鸡汤

成才之路不一定会创造人生奇迹,但一定要有奋发向上的轨迹;成才之路不一定非要跑得最快,但一定需要屡败屡战的韧性;成才之路不一定拥有鲜花掌声,但应进一寸有一寸的欢喜。

今日学习内容

1、JS 红皮书 P401-413 第十四章:DOM

今日笔记

1、文档对象模型(DOM,Document Object Model)是 HTML 和 XML 文档的编程接口。DOM 表示由多层节点构成的文档,通过它开发者可以添加、删除和修改页面的各个部分。
2、节点层级: 任何 HTML 或 XML 文档都可以用 DOM 表示为一个由节点构成的层级结构。节点分很多类型,每种类型对应着文档中不同的信息和(或)标记,也都有自己不同的特性、数据和方法,而且与其他类型有某种关系。这些关系构成了层级,让标记可以表示为一个以特定节点为根的树形结构。以下面的 HTML为例:

1
2
3
4
5
6
7
8
<html> 
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>

DOM 中总共有 12 种节点类型,这些类型都继承一种基本类型。

  • 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 保存着有关节点的信息。这两个属性的值完全取决于节点类型。在使用这两个属性前,最好先检测节点类型,如下所示:
      1
      2
      3
      if (someNode.nodeType == 1){ 
      value = someNode.nodeName; // 会显示元素的标签名
      }
      节点关系: 文档中的所有节点都与其他节点有关系。这些关系可以形容为家族关系,相当于把文档树比作家谱。在 HTML 中,元素是元素的子元素,而元素则是元素的父元素。元素是元素的同胞元素,因为它们有共同的父元素。
      每个节点都有一个 childNodes 属性,其中包含一个 NodeList 的实例。NodeList 是一个类数组对象,用于存储可以按位置存取的有序节点。注意,NodeList 并不是 Array 的实例,但可以使用中括号访问它的值,而且它也有 length 属性。NodeList 对象独特的地方在于,它其实是一个对 DOM 结构的查询,因此 DOM 结构的变化会自动地在 NodeList 中反映出来。我们通常说 NodeList 是实时的活动对象,而不是第一次访问时所获得内容的快照。
      每个节点都有一个 parentNode 属性,指向其 DOM 树中的父元素。childNodes 中的所有节点都有同一个父元素,因此它们的 parentNode 属性都指向同一个节点。此外,childNodes 列表中的每个节点都是同一列表中其他节点的同胞节点。而使用 previousSibling 和 nextSibling 可以在这个列表的节点间导航。这个列表中第一个节点的 previousSibling 属性是 null,最后一个节点的nextSibling 属性也是 null,如下所示:
      1
      2
      3
      4
      5
      if (someNode.nextSibling === null){ 
      alert("Last node in the parent's childNodes list.");
      } else if (someNode.previousSibling === null){
      alert("First node in the parent's childNodes list.");
      }
      因为所有关系指针都是只读的,所以 DOM 又提供了一些操纵节点的方法。最常用的方法是appendChild(),用于在 childNodes 列表末尾添加节点。添加新节点会更新相关的关系指针,包括父节点和之前的最后一个子节点。appendChild()方法返回新添加的节点,如下所示:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      let returnedNode = someNode.appendChild(newNode); 
      alert(returnedNode == newNode); // true
      alert(someNode.lastChild == newNode); // true

      // 假设 someNode 有多个子节点
      let returnedNode = someNode.appendChild(someNode.firstChild);
      alert(returnedNode == someNode.firstChild); // false
      alert(returnedNode == someNode.lastChild); // true

      // 作为最后一个子节点插入
      returnedNode = someNode.insertBefore(newNode, null);
      alert(newNode == someNode.lastChild); // 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
      所有节点类型还共享了两个方法。第一个是 cloneNode(),会返回与调用它的节点一模一样的节点。cloneNode()方法接收一个布尔值参数,表示是否深复制。在传入 true 参数时,会进行深复制,即复制节点及其整个子 DOM 树。如果传入 false,则只会复制调用该方法的节点。复制返回的节点属于文档所有,但尚未指定父节点,所以可称为孤儿节点(orphan)。可以通过 appendChild()、insertBefore()或 replaceChild()方法把孤儿节点添加到文档中。以下面的 HTML 片段为例:
      1
      2
      3
      4
      5
      <ul> 
      <li>item 1</li>
      <li>item 2</li>
      <li>item 3</li>
      </ul>
      如果myList保存着对这个
        元素的引用,则下列代码展示了使用cloneNode()方法的两种方式:
        1
        2
        3
        4
        let deepList = myList.cloneNode(true); 
        alert(deepList.childNodes.length); // 3(IE9 之前的版本)或 7(其他浏览器)
        let shallowList = myList.cloneNode(false);
        alert(shallowList.childNodes.length); // 0
        本节要介绍的最后一个方法是 normalize()。这个方法唯一的任务就是处理文档子树中的文本节点。由于解析器实现的差异或 DOM 操作等原因,可能会出现并不包含文本的文本节点,或者文本节点之间互为同胞关系。在节点上调用 normalize()方法会检测这个节点的所有后代,从中搜索上述两种情形。如果发现空文本节点,则将其删除;如果两个同胞节点是相邻的,则将其合并为一个文本节点。

    3、Document类型: 在浏览器中,文档对象 document 是HTMLDocument 的实例(HTMLDocument 继承 Document),表示整个 HTML 页面。document 是 window对象的属性,因此是一个全局对象。Document 类型的节点有以下特征:
    - nodeType: 9
    - nodeName: “#document”
    - nodeValue: null
    - parentNode: null
    - ownerDocument: null
    - 子节点可以是 DocumentType(最多一个)、Element(最多一个)、ProcessingInstruction或 Comment 类型。

    • 文档子节点: 虽然 DOM 规范规定 Document 节点的子节点可以是 DocumentType、Element、ProcessingInstruction 或 Comment,但也提供了两个访问子节点的快捷方式。第一个是 documentElement 属性,始终指向 HTML 页面中的元素。虽然 document.childNodes 中始终有元素,但使用 documentElement 属性可以更快更直接地访问该元素。假如有以下简单的页面:
      1
      2
      3
      4
      <html> 
      <body>
      </body>
      </html>
      浏览器解析完这个页面之后,文档只有一个子节点,即元素。这个元素既可以通过documentElement 属性获取,也可以通过 childNodes 列表访问,如下所示:
      1
      2
      3
      let html = document.documentElement; // 取得对<html>的引用
      alert(html === document.childNodes[0]); // true
      alert(html === document.firstChild); // true
      作为 HTMLDocument 的实例,document 对象还有一个 body 属性,直接指向元素。因为这个元素是开发者使用最多的元素,所以 JavaScript 代码中经常可以看到 document.body,比如:
      1
      let body = document.body; // 取得对<body>的引用
      Document 类型另一种可能的子节点是 DocumentType。<!doctype>标签是文档中独立的部分,其信息可以通过 doctype 属性(在浏览器中是 document.doctype)来访问,比如:
      1
      let doctype = document.doctype; // 取得对<!doctype>的引用
      另外,严格来讲出现在元素外面的注释也是文档的子节点,它们的类型是 Comment。不过,由于浏览器实现不同,这些注释不一定能被识别,或者表现可能不一致。比如以下 HTML 页面:
      1
      2
      3
      4
      5
      6
      <!-- 第一条注释 --> 
      <html>
      <body>
      </body>
      </html>
      <!-- 第二条注释 -->
    • 文档信息: document 作为 HTMLDocument 的实例,还有一些标准 Document 对象上所没有的属性。这些属性提供浏览器所加载网页的信息。其中第一个属性是 title,包含元素中的文本,通常显示在浏览器窗口或标签页的标题栏。通过这个属性可以读写页面的标题,修改后的标题也会反映在浏览器标题栏上。不过,修改 title 属性并不会改变<title>元素。下面是一个例子:<div class="highlight-container" data-rel="Js"><figure class="iseeu highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 读取文档标题</span></span><br><span class="line"><span class="keyword">let</span> originalTitle = <span class="variable language_">document</span>.<span class="property">title</span>; </span><br><span class="line"><span class="comment">// 修改文档标题</span></span><br><span class="line"><span class="variable language_">document</span>.<span class="property">title</span> = <span class="string">"New page title"</span>;</span><br></pre></td></tr></table></figure></div> 接下来要介绍的 3 个属性是 URL、domain 和 referrer。其中,URL 包含当前页面的完整 URL(地址栏中的 URL),domain 包含页面的域名,而 referrer 包含链接到当前页面的那个页面的 URL。如果当前页面没有来源,则 referrer 属性包含空字符串。所有这些信息都可以在请求的 HTTP 头部信息中获取,只是在 JavaScript 中通过这几个属性暴露出来而已,如下面的例子所示:<div class="highlight-container" data-rel="Js"><figure class="iseeu highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 取得完整的 URL </span></span><br><span class="line"><span class="keyword">let</span> url = <span class="variable language_">document</span>.<span class="property">URL</span>; </span><br><span class="line"><span class="comment">// 取得域名</span></span><br><span class="line"><span class="keyword">let</span> domain = <span class="variable language_">document</span>.<span class="property">domain</span>; </span><br><span class="line"><span class="comment">// 取得来源</span></span><br><span class="line"><span class="keyword">let</span> referrer = <span class="variable language_">document</span>.<span class="property">referrer</span>;</span><br></pre></td></tr></table></figure></div></li> <li>定位元素: 使用 DOM 最常见的情形可能就是获取某个或某组元素的引用,然后对它们执行某些操作。document 对象上暴露了一些方法,可以实现这些操作。getElementById()和 getElementsByTagName()就是 Document 类型提供的两个方法。HTMLDocument 类型上定义的获取元素的第三个方法是getElementsByName()。顾名思义,这个方法会返回具有给定 name 属性的所有元素。</li> <li>特殊集合: document 对象上还暴露了几个特殊集合,这些集合也都是 HTMLCollection 的实例。这些集合是访问文档中公共部分的快捷方式,列举如下。<br> document.anchors 包含文档中所有带 name 属性的<a>元素。<br> document.applets 包含文档中所有<applet>元素(因为<applet>元素已经不建议使用,所以这个集合已经废弃)。<br> document.forms 包含文档中所有<form>元素(与 documentgetElementsByTagName (“form”)返回的结果相同)。<br> document.images 包含文档中所有<img>元素(与 document.getElementsByTagName (“img”)返回的结果相同)。<br> document.links 包含文档中所有带 href 属性的<a>元素。</li> <li>DOM兼容性检测: document.implementation 属性是一个对象,其中提供了与浏览器 DOM 实现相关的信息和能力。</li> <li>文档写入: document 对象有一个古老的能力,即向网页输出流中写入内容。这个能力对应 4 个方法:write()、writeln()、open()和 close()。其中,write()和 writeln()方法都接收一个字符串参数,可以将这个字符串写入网页中。write()简单地写入文本,而 writeln()还会在字符串末尾追加一个换行符(\n)。</li> </ul> </div> <ul class="post-tags-box text-lg mt-1.5 flex-wrap justify-center flex md:hidden"> <li class="tag-item mx-0.5"> <a href="/tags/journal/">#journal</a>  </li> </ul> <div class="article-nav my-8 flex justify-between items-center px-2 sm:px-6 md:px-8"> <div class="article-prev border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2"> <a class="prev" rel="prev" href="/undefined/2025-02-19/" > <span class="left arrow-icon flex justify-center items-center"> <i class="fa-solid fa-chevron-left"></i> </span> <span class="title flex justify-center items-center"> <span class="post-nav-title-item">2025-02-19 日报 Day102</span> <span class="post-nav-item">上一篇</span> </span> </a> </div> <div class="article-next border-border-color shadow-redefine-flat shadow-shadow-color-2 rounded-medium px-4 py-2 hover:shadow-redefine-flat-hover hover:shadow-shadow-color-2"> <a class="next" rel="next" href="/undefined/2025-02-17/" > <span class="title flex justify-center items-center"> <span class="post-nav-title-item">2025-02-17 日报 Day100</span> <span class="post-nav-item">下一篇</span> </span> <span class="right arrow-icon flex justify-center items-center"> <i class="fa-solid fa-chevron-right"></i> </span> </a> </div> </div> </div> <div class="toc-content-container"> <div class="post-toc-wrap"> <div class="post-toc"> <div class="toc-title">此页目录</div> <div class="page-title">2025-02-18 日报 Day101</div> <ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%8A%E6%97%A5%E5%AD%A6%E4%B9%A0%E5%86%85%E5%AE%B9"><span class="nav-text">今日学习内容</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BB%8A%E6%97%A5%E7%AC%94%E8%AE%B0"><span class="nav-text">今日笔记</span></a></li></ol> </div> </div> </div> </div> </div> </div> <div class="main-content-footer"> <footer class="footer mt-5 py-5 h-auto text-base text-third-text-color relative border-t-2 border-t-border-color"> <div class="info-container py-3 text-center"> <div class="text-center"> © <span>2022</span> - 2025  <i class="fa-solid fa-heart fa-beat" style="--fa-animation-duration: 0.5s; color: #f54545"></i>  <a href="/">Yuyang</a> <p class="post-count space-x-0.5"> <span> 共 199 篇文章 </span> </p> </div> <script data-swup-reload-script src="https://cn.vercount.one/js"></script> <div class="relative text-center lg:absolute lg:right-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-right"> <span id="busuanzi_container_site_uv" class="lg:!block"> <span class="text-sm">访问人数</span> <span id="busuanzi_value_site_uv"></span> </span> <span id="busuanzi_container_site_pv" class="lg:!block"> <span class="text-sm">总访问量</span> <span id="busuanzi_value_site_pv"></span> </span> </div> <div class="relative text-center lg:absolute lg:left-[20px] lg:top-1/2 lg:-translate-y-1/2 lg:text-left"> <span class="lg:block text-sm">由 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="relative top-[2px] inline-block align-baseline" version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1rem" height="1rem" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><path fill="#0E83CD" d="M256.4,25.8l-200,115.5L56,371.5l199.6,114.7l200-115.5l0.4-230.2L256.4,25.8z M349,354.6l-18.4,10.7l-18.6-11V275H200v79.6l-18.4,10.7l-18.6-11v-197l18.5-10.6l18.5,10.8V237h112v-79.6l18.5-10.6l18.5,10.8V354.6z"/></svg><a target="_blank" class="text-base" href="https://hexo.io">Hexo</a> 驱动</span> <span class="text-sm lg:block">主题 <a class="text-base" target="_blank" href="https://github.com/EvanNotFound/hexo-theme-redefine">Redefine v2.6.4</a></span> </div> </div> </footer> </div> </div> <div class="post-tools"> <div class="post-tools-container"> <ul class="article-tools-list"> <!-- TOC aside toggle --> <li class="right-bottom-tools page-aside-toggle"> <i class="fa-regular fa-outdent"></i> </li> <!-- go comment --> </ul> </div> </div> <div class="right-side-tools-container"> <div class="side-tools-container"> <ul class="hidden-tools-list"> <li class="right-bottom-tools tool-font-adjust-plus flex justify-center items-center"> <i class="fa-regular fa-magnifying-glass-plus"></i> </li> <li class="right-bottom-tools tool-font-adjust-minus flex justify-center items-center"> <i class="fa-regular fa-magnifying-glass-minus"></i> </li> <li class="right-bottom-tools tool-dark-light-toggle flex justify-center items-center"> <i class="fa-regular fa-moon"></i> </li> <!-- rss --> <li class="right-bottom-tools tool-scroll-to-bottom flex justify-center items-center"> <i class="fa-regular fa-arrow-down"></i> </li> </ul> <ul class="visible-tools-list"> <li class="right-bottom-tools toggle-tools-list flex justify-center items-center"> <i class="fa-regular fa-cog fa-spin"></i> </li> <li class="right-bottom-tools tool-scroll-to-top flex justify-center items-center"> <i class="arrow-up fas fa-arrow-up"></i> <span class="percent"></span> </li> </ul> </div> </div> <div class="image-viewer-container"> <img src=""> </div> <div class="search-pop-overlay"> <div class="popup search-popup"> <div class="search-header"> <span class="search-input-field-pre"> <i class="fa-solid fa-keyboard"></i> </span> <div class="search-input-container"> <input autocomplete="off" autocorrect="off" autocapitalize="off" placeholder="搜索..." spellcheck="false" type="search" class="search-input" > </div> <span class="popup-btn-close"> <i class="fa-solid fa-times"></i> </span> </div> <div id="search-result"> <div id="no-result"> <i class="fa-solid fa-spinner fa-spin-pulse fa-5x fa-fw"></i> </div> </div> </div> </div> </main> <script src="/js/libs/Swup.min.js"></script> <script src="/js/libs/SwupSlideTheme.min.js"></script> <script src="/js/libs/SwupScriptsPlugin.min.js"></script> <script src="/js/libs/SwupProgressPlugin.min.js"></script> <script src="/js/libs/SwupScrollPlugin.min.js"></script> <script src="/js/libs/SwupPreloadPlugin.min.js"></script> <script> const swup = new Swup({ plugins: [ new SwupScriptsPlugin({ optin: true, }), new SwupProgressPlugin(), new SwupScrollPlugin({ offset: 80, }), new SwupSlideTheme({ mainElement: ".main-content-body", }), new SwupPreloadPlugin(), ], containers: ["#swup"], }); </script> <script src="/js/tools/imageViewer.js" type="module"></script> <script src="/js/utils.js" type="module"></script> <script src="/js/main.js" type="module"></script> <script src="/js/layouts/navbarShrink.js" type="module"></script> <script src="/js/tools/scrollTopBottom.js" type="module"></script> <script src="/js/tools/lightDarkSwitch.js" type="module"></script> <script src="/js/layouts/categoryList.js" type="module"></script> <script src="/js/tools/localSearch.js" type="module"></script> <script src="/js/tools/codeBlock.js" type="module"></script> <script src="/js/layouts/lazyload.js" type="module"></script> <script src="/js/libs/Typed.min.js"></script> <script src="/js/plugins/typed.js" type="module"></script> <div class="post-scripts" data-swup-reload-script> <script src="/js/tools/tocToggle.js" type="module"></script> <script src="/js/layouts/toc.js" type="module"></script> <script src="/js/plugins/tabs.js" type="module"></script> </div> </body> </html>