陈大剩博客

前端温习(二): Javascriput 核心对象 Document 对象

  • 陈大剩
  • 2023-01-30 12:10:43
  • 782

Document 对象

当浏览器载入 HTML 文档, 它就会成为 Document 对象。

Document 对象是 HTML 文档的根节点。

Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。

在 HTML DOM (Document Object Model) 中 , 每一个元素都是 节点:

  • 文档是一个文档节点
  • 所有的 HTML 元素都是元素节点
  • 所有 HTML 属性都是属性节点
  • 文本插入到 HTML 元素是文本节点。are text nodes
  • 注释是注释节点

Document不同获取办法

  • 对于正常的网页,直接使用 documentwindow.document
  • 对于 iframe 载入的网页,使用 iframe 节点的 contentDocument 属性
  • Ajax 操作返回的文档,使用 XMLHttpRequest 对象的 responseXML 属性
  • 对于某个节点包含的文档,使用该节点的 ownerDocument 属性。

提示:Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问。

Document 对象属性和方法

属性

属性 说明
document.activeElement 返回当前获取焦点元素
document.anchors 返回对文档中所有 Anchor 对象的引用
document.baseURI 返回文档的绝对基础 URI
document.body 返回文档的body元素
document.cookie 设置或返回与当前文档有关的所有 cookie
document.doctype 返回与文档相关的文档类型声明 (DTD)
document.documentElement 返回文档的根节点
document.domain 返回当前文档的域名
document.referrer 返回载入当前文档的文档的 URL
document.links 返回对文档中所有 Area 和 Link 对象引用
document.title 返回当前文档的标题
document.scripts 返回页面中所有脚本的集合

方法

方法 说明
document.write() 向文档写 HTML 表达式 或 JavaScript 代码
document.writeln() 等同于 write() 方法,不同的是在每个表达式之后写一个换行符
document.adoptNode(node) 从另外一个文档返回 adapded 节点到当前文档
document.addEventListener() 向文档添加句柄
document.open() 打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出
document.close() 关闭用 document.open() 方法打开的输出流,并显示选定的数据
document.createAttribute() 创建一个属性节点
document.createComment() createComment() 方法可创建注释节点
document.createDocumentFragment() 创建空的 DocumentFragment 对象,并返回此对象
document.createElement() 创建元素节点
document.createTextNode() 创建文本节点
document.getElementsByClassName() 返回文档中所有指定类名的元素集合,作为 NodeList 对象
document.getElementById() 返回对拥有指定 id 的第一个对象的引用
document.getElementsByName() 返回带有指定名称的对象集合
document.getElementsByTagName() 返回带有指定标签名的对象集合
document.importNode() 把一个节点从另一个文档复制到该文档以便应用
document.normalize() 删除空文本节点,并连接相邻节点
document.normalizeDocument() 删除空文本节点,并连接相邻节点的
document.querySelector() 返回文档中匹配指定的CSS选择器的第一元素
document.querySelectorAll() document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表
document.removeEventListener() 移除文档中的事件句柄(由 addEventListener() 方法添加)
document.renameNode() 重命名元素或者属性节点

使用

由于属性和方法比较多,就把一些常用的一些属性和方法展开说明。

属性

  • doctype
    对于 HTML 文档来说,document 对象一般有两个子节点。第一个子节点是 document.doctype,它是一个对象,包含了当前文档类型(Document Type Declaration,简写DTD)信息。对于 HTML5 文档,该节点就代表 <!DOCTYPE html>。如果网页没有声明 DTD,该属性返回 null

    // document.firstChild 通常就返回这个节点
    var doctype = document.doctype;
       
    doctype 
    // "<!DOCTYPE html>"
    doctype.name 
    // "html"
    
  • documentElement
    document.documentElement 属性,表示当前文档的根节点(root)。它通常是 document 节点的第二个子节点,紧跟在 document.doctype 节点后面。
    对于 HTML 网页,该属性返回 HTML 节点,代表 <html lang="en">

  • defaultView
    defaultView 属性,在浏览器中返回 document 对象所在的 window 对象,否则返回 null

  • body
    body 属性返回当前文档的 bodyframeset 节点,如果不存在这样的节点,就返回 null

    这个属性是可写的,如果对其写入一个新的节点,会导致原有的所有子节点被移除。

  • head
    head 属性返回当前文档的 head 节点。如果当前文档有多个 head,则返回第一个。

  • activeElement
    activeElement 属性返回当前文档中获得焦点的那个元素。用户通常可以使用 tab 键移动焦点,使用空格键激活焦点,比如如果焦点在一个链接上,此时按一下空格键,就会跳转到该链接。

  • documentURI、URL
    documentURI 属性和 URL 属性都返回当前文档的网址。不同之处是 documentURI 属性是所有文档都具备的,URL 属性则是 HTML 文档独有的。

  • domain
    domain 属性返回当前文档的域名。比如,某张网页的网址是 http://www.example.com/hello.htmldomain 属性就等于 www.example.com 。如果无法获取域名,该属性返回 null

    // 如果当前域名等于指定域名,则关闭窗口。
    var badDomain = "www.example.xxx";
     
    if (document.domain === badDomain)
      window.close();
    

    二级域名的情况下,domain 属性可以设置为对应的一级域名。比如,当前域名是 sub.example.com,则 domain 属性可以设置为 example.com。除此之外的写入,都是不可以的。

  • lastModified
    lastModified 属性返回当前文档最后修改的时间戳,格式为字符串。

    document.lastModified
    // '08/05/2021 17:34:49'
      
    if (Date.parse(doc1.lastModified) Date.parse(doc2.lastModified)) {
      // ...
    }
    

    注意,lastModified 属性的值是字符串,所以不能用来直接比较,两个文档谁的日期更新,需要用 Date.parse 方法转成时间戳格式,才能进行比较。

  • location
    location 属性返回一个只读对象,提供了当前文档的 URL 信息。

    // 假定当前网址为http://user:passwd@www.example.com:4097/path/a.html?x=111#part1
     
    document.location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
    document.location.protocol // "http:"
    document.location.host // "www.example.com:4097"
    document.location.hostname // "www.example.com"
    document.location.port // "4097"
    document.location.pathname // "/path/a.html"
    document.location.search // "?x=111"
    document.location.hash // "#part1"
    document.location.user // "user"
    document.location.password // "passed"
     
    // 跳转到另一个网址
    document.location.assign('http://www.google.com')
    // 优先从服务器重新加载
    document.location.reload(true)
    // 优先从本地缓存重新加载(默认值)
    document.location.reload(false)
    // 跳转到另一个网址,但当前文档不保留在history对象中,
    // 即无法用后退按钮,回到当前文档
    document.location.assign('http://www.google.com')
    // 将location对象转为字符串,等价于document.location.href
    document.location.toString()
    
  • referrer
    referrer 属性返回一个字符串,表示前文档的访问来源,如果是无法获取来源或是用户直接键入网址,而不是从其他网页点击,则返回一个空字符串。

  • title
    title 属性返回当前文档的标题,该属性是可写的。

    document.title = '新标题';
    
  • characterSet
    characterSet 属性返回渲染当前文档的字符集,比如 UTF-8ISO-8859-1

  • readyState
    readyState 属性返回当前文档的状态,共有三种可能的值,加载 HTML 代码阶段(尚未完成解析)是“loading”,加载外部资源阶段是“interactive”,全部加载完成是“complete”。

    // 基本检查
    if (document.readyState === 'complete') {
      // ...
    }
     
    // 轮询检查
    var interval = setInterval(function() {
      if (document.readyState === 'complete') {
        clearInterval(interval);
        // ...
      }
    }, 100);
    
  • designModed
    designMode 属性控制当前 document 是否可编辑。通常会打开 iframedesignMode 属性,将其变为一个所见即所得的编辑器。

    iframe_node.contentDocument.designMode = "on";
    
  • implementation
    implementation 属性返回一个对象,用来甄别当前环境部署了哪些 DOM 相关接口。implementation 属性的 hasFeature 方法,可以判断当前环境是否部署了特定版本的特定接口。

    // 当前环境部署了DOM HTML 2.0版和MutationEvents的2.0版。
    document.implementation.hasFeature( 'HTML, 2.0 ')
    // true
     
    document.implementation.hasFeature('MutationEvents','2.0')
    // true
    
  • compatMode
    compatMode 属性返回浏览器处理文档的模式,可能的值为 BackCompat(向后兼容模式)和 CSS1Compat(严格模式)。

  • anchors,embeds,forms,images,links,scripts,styleSheets
    这几个属性都是返回文档内部特定元素的集合。这些集合都是动态的,原节点有任何变化,立刻会反映在集合中

    • anchors 返回网页中所有的 a 节点元素【必须指定了 name属性的 a 元素】
    • embeds 返回网页中所有嵌入对象【即embed标签】,返回的格式为类似数组的对象(nodeList)
    • forms 返回页面中所有表单
    • images 返回页面所有图片元素【即img标签】
    • links 返回当前文档所有的链接元素【即 a 标签,或者说具有 href 属性的元素】
    • scripts 返回当前文档的所有脚本【script标签】
    • styleSheets 返回一个类似数组的对象,包含了当前网页的所有样式表

方法

  • open()
    用于新建一个文档,供 write 方法写入内容。它实际上等于清除当前文档,重新写入内容。不要将此方法与 window.open() 混淆,后者用来打开一个新窗口,与当前文档无关。

  • close
    用于关闭 open 方法所新建的文档。一旦关闭,write 方法就无法写入内容了。如果再调用 write 方法,就等同于又调用 open 方法,新建一个文档,再写入内容。

  • write()
    用于向当前文档写入内容。只要当前文档还没有用 close 方法关闭,它所写入的内容就会追加在已有内容的后面。

    // 页面显示“helloworld”
    document.open();
    document.write("hello");
    document.write("world");
    document.close();
    

    如果页面已经渲染完成(DOMContentLoaded 事件发生之后),再调用 write 方法,它会先调用 open 方法,擦除当前文档所有内容,然后再写入。

    document.addEventListener("DOMContentLoaded", function(event) {
      document.write('<p>Hello World!</p>');
    });
     
    // 等同于
     
    document.addEventListener("DOMContentLoaded", function(event) {
      document.open();
      document.write('<p>Hello World!</p>');
      document.close();
    });
    

    如果在页面渲染过程中调用 write 方法,并不会调用 open 方法。(可以理解成,open 方法已调用,但 close 方法还未调用。)

    <html>
    <body>
    hello
    <script type="text/javascript">
      document.write("world")
    </script>
    </body>
    </html>
    

    注意:虽然调用close方法之后,无法再用write方法写入内容,但这时当前页面的其他DOM节点还是会继续加载。

    // 还是会显示“hello world”
    <script type="text/javascript">
      document.open();
      document.write("hello");
      document.close();
    </script>
    

    总之,除了某些特殊情况,应该尽量避免使用document.write这个方法

  • writeln()
    document.writeln 方法与 write 方法完全一致,除了会在输出内容的尾部添加换行符

    document.write(1);
    document.write(2);
    // 12
       
    document.writeln(1);
    document.writeln(2);
    // 1
    // 2
    //
    

    注意:writeln方法添加的是ASCII码的换行符,渲染成HTML网页时不起作用。

  • hasFocus()
    返回一个布尔值,表示当前文档之中是否有元素被激活或获得焦点。

    focused = document.hasFocus();
    

    注意:有焦点的文档必定被激活(active),反之不成立,激活的文档未必有焦点。比如如果用户点击按钮,从当前窗口跳出一个新窗口,该新窗口就是激活的,但是不拥有焦点。

  • querySelector()
    返回匹配指定的 CSS 选择器的元素节点。如果有多个节点满足匹配条件,则返回第一个匹配的节点。如果没有发现匹配的节点,则返回 null

    var el1 = document.querySelector('.myclass');
    var el2 = document.querySelector('#myParent > [ng-click]');
    

    querySelector 方法无法选中 CSS 伪元素

  • **getElementById()**【非常常用的一个方法】
    返回匹配指定 ID 属性的元素节点。如果没有发现匹配的节点,则返回 null

    var elem = document.getElementById("para1");
    

    getElementById 方法与 querySelector 方法都能获取元素节点,不同之处是 querySelector 方法的参数使用 CSS 选择器语法,getElementById 方法的参数是 HTML 标签元素的 id 属性。

    // 两个方法都能选中id为myElement的元素,但是getElementById()比querySelector()效率高得多
    document.getElementById('myElement')
    document.querySelector('#myElement')
    

    注意:在搜索匹配节点时,id 属性是大小写敏感的。比如,如果某个节点的 id 属性是 main,那么 document.getElementById("Main") 将返回 null,而不是指定节点。

  • querySelectorAll()
    返回匹配指定的 CSS 选择器的所有节点,返回的是 NodeList 类型的对象。NodeList 对象不是动态集合,所以元素节点的变化无法实时反映在返回结果中。

    // 返回class属性是note或alert的div元素
    elementList = document.querySelectorAll(selectors);
    
    // 逗号分隔的多个CSS选择器,返回所有匹配其中一个选择器的元素
    var matches = document.querySelectorAll('div.note, div.alert');
    
    // 支持复杂的CSS选择器。
    // 选中data-foo-bar属性等于someval的元素
    document.querySelectorAll('[data-foo-bar="someval"]');
     
    // 选中myForm表单中所有不通过验证的元素
    document.querySelectorAll('#myForm :invalid');
     
    // 选中div元素,那些class含ignore的除外
    document.querySelectorAll('DIV:not(.ignore)');
     
    // 同时选中div,a,script三类元素
    document.querySelectorAll('DIV, A, SCRIPT');
    

    如果 querySelectorAll 方法和 getElementsByTagName 方法的参数是字符串“*”,则会返回文档中的所有 HTML 元素节点。与 querySelector 方法一样,querySelectorAll 方法无法选中 CSS 伪元素。

  • **getElementsByClassName()**【非常常用的一个方法】
    返回一个类似数组的对象(HTMLCollection类型的对象),包括了所有 class 名字符合指定条件的元素(搜索范围包括本身),元素的变化实时反映在返回结果中。这个方法不仅可以在 document 对象上调用,也可以在任何元素节点上调用。

    // document对象上调用
    var elements = document.getElementsByClassName(names);
    // 非document对象上调用
    var elements = rootElement.getElementsByClassName(names);
    
    // 参数可以是多个空格分隔的class名字,返回同时具有这些节点的元素。
    // 选择同时具有red和test的元素
    document.getElementsByClassName('red test');
    
  • **getElementsByTagName()**【非常常用的一个方法】
    返回所有指定标签的元素(搜索范围包括本身)。返回值是一个 HTMLCollection 对象,也就是说,搜索结果是一个动态集合,任何元素的变化都会实时反映在返回的集合中。这个方法不仅可以在 document 对象上调用,也可以在任何元素节点上调用。

    // 返回当前文档的所有p元素节点
    var paras = document.getElementsByTagName("p");
    

    注意:getElementsByTagName方法会将参数转为小写后,再进行搜索

  • getElementsByName()
    用于选择拥有 name 属性的 HTML 元素,比如 formimgframeembedobject,返回一个 NodeList 格式的对象,不会实时反映元素的变化

    // 假定有一个表单是<form name="x"></form>
    var forms = document.getElementsByName("x");
    forms[0].tagName // "FORM"
    

    注意:在IE浏览器使用这个方法,会将没有 name 属性、但有同名 id 属性的元素也返回,所以name和id属性最好设为不一样的值。

  • elementFromPoint()
    返回位于页面指定位置的元素

    // 返回相对于当前窗口左上角的横坐标和纵坐标,单位是CSS像素
    var element = document.elementFromPoint(x, y);
    
  • createElement()
    用来生成 HTML 元素节点

    var element = document.createElement(tagName);
    // 实例
    var newDiv = document.createElement("div");
    

注意:createElement 方法的参数为元素的标签名,即元素节点的 tagName 属性。如果传入大写的标签名,会被转为小写。如果参数带有尖括号(即<和>)或者是 null,会报错。

  • createTextNode()
    用来生成文本节点,参数为所要生成的文本节点的内容

    // 新建一个div节点和一个文本节点,文本节点插入div节点
    var newDiv = document.createElement("div");
    var newContent = document.createTextNode("Hello");
    newDiv.appendChild(newContent);
    
  • createAttribute()
    生成一个新的属性对象节点,并返回它。

    attribute = document.createAttribute(name);
    // createAttribute 方法的参数 name,是属性的名称
    
    var node = document.getElementById("div1");
    var a = document.createAttribute("my_attrib");
    a.value = "newVal";
    node.setAttributeNode(a);
     
    // 等同于
    var node = document.getElementById("div1");
    node.setAttribute("my_attrib", "newVal");
    
  • createDocumentFragment()
    生成一个 DocumentFragment 对象。DocumentFragment 对象是一个存在于内存的 DOM 片段,但是不属于当前文档,常常用来生成较复杂的 DOM 结构,然后插入当前文档。这样做的好处在于,因为 DocumentFragment 不属于当前文档,对它的任何改动,都不会引发网页的重新渲染,比直接修改当前文档的 DOM 有更好的性能表现。

    var docfrag = document.createDocumentFragment();
     
    [1, 2, 3, 4].forEach(function(e) {
      var li = document.createElement("li");
      li.textContent = e;
      docfrag.appendChild(li);
    });
     
    document.body.appendChild(docfrag);
    
  • createEvent()
    生成一个事件对象,该对象可以被 element.dispatchEvent 方法使用,触发指定事件

    // createEvent 方法的参数是事件类型,比如 UIEvents、MouseEvents、MutationEvents、HTMLEvents
    var event = document.createEvent('Event');
    event.initEvent('build', true, true);
    document.addEventListener('build', function (e) {
      // ...
    }, false);
    document.dispatchEvent(event);
    
  • reateNodeIterator()
    createNodeIterator 方法返回一个 DOM 的子节点遍历器。

    var nodeIterator = document.createNodeIterator(
      document.body,
      NodeFilter.SHOW_ELEMENT
    );
    

    上面代码返回 body 元素的遍历器。createNodeIterator 方法的第一个参数为遍历器的根节点,第二个参数为所要遍历的节点类型,这里指定为元素节点。其他类型还有所有节点(NodeFilter.SHOW_ALL)、文本节点(NodeFilter.SHOW_TEXT)、评论节点(NodeFilter.SHOW_COMMENT)等。

    所谓“遍历器”,在这里指可以用 nextNode 方法和 previousNode 方法依次遍历根节点的所有子节点。

    var nodeIterator = document.createNodeIterator(document.body);
    var pars = [];
    var currentNode;
     
    while (currentNode = nodeIterator.nextNode()) {
      pars.push(currentNode);
    }
    

    上面代码使用遍历器的 nextNode 方法,将根节点的所有子节点,按照从头部到尾部的顺序,读入一个数组。nextNode 方法先返回遍历器的内部指针所在的节点,然后会将指针移向下一个节点。所有成员遍历完成后,返回 nullpreviousNode 方法则是先将指针移向上一个节点,然后返回该节点。

    // currentNode和previousNode都指向同一个的节点
    var nodeIterator = document.createNodeIterator(
      document.body,
      NodeFilter.SHOW_ELEMENT
    );
     
    var currentNode = nodeIterator.nextNode();
    var previousNode = nodeIterator.previousNode();
     
    currentNode === previousNode // true
    

    注意:遍历器返回的第一个节点,总是根节点

  • createTreeWalker()
    返回一个 DOM 的子树遍历器。它与 createNodeIterator 方法的区别在于,后者只遍历子节点,而它遍历整个子树。

    // createTreeWalker 第一个参数,是所要遍历的根节点,第二个参数指定所要遍历的节点类型
    // 遍历body节点下属的所有元素节点,将它们插入nodeList数组
    var treeWalker = document.createTreeWalker(
      document.body,
      NodeFilter.SHOW_ELEMENT
    );
       
    var nodeList = [];
     
    while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode);
    
  • adoptNode()
    将某个节点,从其原来所在的文档移除,插入当前文档,并返回插入后的新节点。

    // importNode 方法从外部文档拷贝指定节点,插入当前文档
    var node = document.importNode(externalNode, deep);
    
  • importNode()
    用于创造一个外部节点的拷贝,然后插入当前文档。它的第一个参数是外部节点,第二个参数是一个布尔值,表示对外部节点是深拷贝还是浅拷贝,默认是浅拷贝(false)。虽然第二个参数是可选的,但是建议总是保留这个参数,并设为true。

    // 从iframe窗口,拷贝一个指定节点myNode,插入当前文档
    var iframe = document.getElementsByTagName("iframe")[0];
    var oldNode = iframe.contentWindow.document.getElementById("myNode");
    var newNode = document.importNode(oldNode, true);
    document.getElementById("container").appendChild(newNode);
    

    注意:importNode 方法只是拷贝外部节点,这时该节点的父节点是 null。下一步还必须将这个节点插入当前文档的 DOM 树。

分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[115]| 评论总数[9]| 登录用户[22]| 时间点[118]

logo

登入

社交账号登录