博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从DOM选择器的返回值说起
阅读量:6457 次
发布时间:2019-06-23

本文共 3142 字,大约阅读时间需要 10 分钟。

原文发布在我的独立博客上 ~:

抛开大大解放生产力的jQuery,使用JS获取元素要使用getElementById方法,或类似的getElementsByTagName, getElementsByClassName,getElementsByName. 第一种情况下,根据ID获取时,返回值是唯一的元素;而根据TagName, ClassName 等获取时候,返回值是包含所有符合条件的多个元素的“列表”。此处“列表”要加双引号,是因为严格来说,JavaScript乃至DOM元素中并没有所谓“列表”或List的数据类型/对象,既然不能称为列表,那么它们到底是啥?

这篇blog就试图从getElement(s)的返回值说起,往上扯一些早就该了解,但总是似懂非懂的简单的DOM基础知识。

getElements方法的返回值

  • getElementsByClassName('myClass')获取指定类名为myClass的元素,getElementsByTagName('some-tag')获取标签为'some-tag'的元素,它们的返回值都是 HTMLCollection 对象

    Screen-20150510-006.png

  • getElementsByName('myName')获取标记了name属性为myName的元素,它的返回值是NodeList对象

    Screen-20150510-007.png

  • getElementById('myId')获取唯一id属性为myId的元素。有趣的是,当访问该元素的constructor.name属性时,可以得到不同的值。form元素对应HTMLFormElement对象, main标签则对应HTMLElement对象,这应该是从面向对象的角度看,不同类型的元素属于不同的对象实例。

    Screen-20150510-008.png

  • querySelectorquerySelectorAll方法是HTML5新增的Web API,它们接受selector参数,selector正是我们常用的CSS选择器。不同之处在于,querySelector('form')返回的是页面中的第一个'form'元素,而querySelectorAll('form')返回NodeList类型,它们是所有form的列表。

    Screen-20150510-010.png

NodeList与HTMLCollection

接着来看这两个对象,它们都由多个元素组成一个“列表”,或者说“数组”,我们也可以像使用数组一样方便地用下标访问单个元素。但是它们仅仅是Array-like,并没有Array对象的其他常用方法,比如forEach.

javascriptvar buttons = document.getElementsByTagName('button');console.log(buttons[1]);  // 输出第2个button元素console.log(buttons.forEach); // undefiedconsole.log(buttons.filter); //undefiedvar next_nodes = document.getElementsByName('next');console.log(next_nodes[0]); //输出列表中第1个元素console.log(next_nodes.forEach);    //undefied

除了以上提到的getElements方法之外

  • NodeList也是Node.childNodes, document.querySelector的返回值类型
  • HTMLCollection也是Node.children, document.forms等的对象类型

在使用getElements方法时,NodeList和HTMLCollection好像并没什么不一一样的,但是从字面上讲,一个是节点列表,一个是HTML(元素)集合,并不是一回事。他们的不同可以从另外两个方法看出,它们是childNodes和children,下面是一个合适的例子。

Node.childNodes与Node.children的区别

html
text in div
Link
Strong Text Strong Link
javascriptmydiv = document.querySelector('div');console.log(mydiv.children);    // 不含#text "text in div"和注释console.log(mydiv.childNodes);  // 含文字"text in div"和注释
  • mydiv.children获得的,是<div>的子标签代表的元素,所以示例中的text in span并不属于span.children
  • mydiv.childNodes获得的,是包含文本内容在内的所有子节点。所谓节点,正是浏览器在构造DOM树的每一个不可或缺的元素,当然少不了必须的文本节点。

所以它们不同就在于一个获取的是元素,一个获取所有节点。

从Element到Node到DOM

到底元素和节点有什么不同,看原型链。

<a>元素为例,调用mydiv.children[0].constructor.name,可知<a>Link</a>元素的类型HTMLAnchorElement; HTMLAnchorElement的原型链为:

HTMLAnchorElement --> HTMLElement --> Element --> Node --> EventTarget --> Object

调用mydiv.childNodes[0].constructor.name,可知<!-- this is a comment -->节点的对象类型Comment,类似也可以得到文本节点的类型Text,它们的原型链为:

Comment --> CharacterData --> Node --> EventTarget --> Object

Text --> CharacterData -- Node -- EventTarget --> Object

看到原型链就可以豁然开朗了,Node是包含Element和Text, Comment在内的概念,而HTMLElement只是Node的一个子集。

除了上面示例的几个节点类型,Node包含的类型如下;对任意一个节点myNode,myNode.nodeType属性就是它的类型。

Screen-20150510-009.png

图片截自 , thumb down图标代表废弃API,是不推荐使用的类型

终于扯到最基本的DOM概念了,DOM事关重大,然而原理其实也就是两句话的事儿。

DOM == Document Object Modle(文档结构模型),浏览器收到一个HTML页面后,根据页面结构构建一个DOM树,DOM树就是由不同类型的节点(Node)所组成的。在HTML文档中,一条注释语句是一个Node,一个HTML元素也是Node,甚至<!DOCTYPE html>也是一个Node。有了Node对象,一生二,二生三,三生万物;除了事件和ajax请求,前端编程说白了就剩下来使用浏览器提供的DOM API来对Node进行各种操作。

当然,观察Node的原型链,可以看到处于它上一层的是 EventTarget对象,这意味着Node都继承了EventTarget的属性和方法,最常见的当然是.addEventListener。这正是javascript在前端能够实现各种可能性的原因,一切节点都可以绑定事件


参考:

1.
2.
3.
4.

转载地址:http://nmizo.baihongyu.com/

你可能感兴趣的文章
[System Design] 系统设计 (2) -- 数据库设计
查看>>
一个有意思的解密
查看>>
操作系统思考 第五章 更多的位与字节
查看>>
linux下配置samba服务
查看>>
scala-graph by example (0) visualization
查看>>
fir.im Weekly - 从零开始创建 Android 新项目
查看>>
Survivor空间溢出实例
查看>>
RN 0.26 引用方式中哪些属于React,哪些属于React Native
查看>>
[转][整理]Linux下找不到共享库(shared object)
查看>>
浅谈浏览器端JavaScript跨域解决方法
查看>>
Yii源码解读 - 事件
查看>>
同步与异步、异步与回调
查看>>
[Algo] Print Matrix Diagonal 对角打印
查看>>
近乎 5.3 发布,SNS 社区系统
查看>>
【直播回顾】蚂蚁金服高级开发工程师萧恺:IDEA 插件开发入门教程 ...
查看>>
全明星投资融资5亿美元,曾下注亏损百亿的滴滴,及商汤、陆金所等独角兽 ...
查看>>
(TPC-H测试 SF=10,SF=200) PostgreSQL 11 vs 10 vs Deepgreen
查看>>
Android中的 targetsdkversioin
查看>>
51Talk2019战略升级,发布互动教学产品妖果AI
查看>>
H3C交换机配件RS232配置线(DB9针转RJ45)
查看>>