从一个作业题开始:一个页面的所用HTML标签种类。
我的做法:
var dom = document.querySelectorAll("*"); //取出所有的标签
var str = []; //建立一个数组装最后的标签
for(var i=0,len=dom.length; i<len;i++){
//去重
if(str.indexOf(dom[i].nodeName) < 0){
str.push(dom[i].nodeName);
}
}
1. 取出所有HTML标签
取出所有的HTML元素,两种方式:
getElementsByTagName(" * ");
querySelectorAll(" * ");
用第一种方式取出的HTML标签会返回一个HTMLCollection对象,HTMLCollection对象提供了一些访问元素的方法,这不是重点,重点是通过这种方式查询的是动态的,并不是访问时所留下的一个快照。动态的还有nodeList对象。
在循环动态DOM时,在初始化时就应该把长度缓存下来,否则,每次循环都会去访问DOM,如果遇上,在循环里再添加一点这个元素,就会死循环了。
for(var i=0,len = div.length; i<len;i++){
//操作
}
用第二种方式返回的是一个nodeList实例,本来所有nodeList都是基于文档的实时查询,但是querySelectorAll是个例外,他的实现就是在访问时留下的一组快照。
示例:
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<script>
var query = document.querySelectorAll("div");
var tag = document.getElementsByTagName("div");
console.log(query);
console.log(tag);
//添加元素
var div = document.createElement("div");
var text = document.createTextNode("5");
div.appendChild(text);
document.body.appendChild(div);
console.log(query);
console.log(tag);
结果:
2. 数组方法
取出的集合是类数组,如何把类数组转换成数组(可以不用转也可以循环取出标签值)。
数组转换方法:
Array.prototype.slice.call(dom);//返回一个新数组,不会改变原来数组。
也可以使用 [].slice.call(dom)
取出标签值:
nodeName 与 tagName.
既然要去标签还是推荐使用tagName。
对于元素节点nodeName与tagName保存的始终都是元素的标签名,如果不是元素节点,nodeName返回的就是节点的类型,tagName则是undefined。
转成数组后数组每一项保存的是元素节点,取出保存的标签值。可以使用数组map方法,返回指定函数调用结果组成的数组。
Array.prototype.slice.call(dom).map(function(item,index,arr){
//item数组的每一项
//index数组下标索引
//原数组
return item.tagName;
})
也可以使用es6的扩展运算符转数组[...dom]
ES6数组的扩展
去重:
数组方法:
indexOf()与lastIndexOf()接收两个参数,要查找的项和可选的起点索引。
一个是从前开始查找,查到第一个就返回索引,没有查到就返回-1.
另一个是从后开始查询。
ES6 Set和Map数据结构
最终这个题最简单的写法:
var s = new Set([...document.getElementsByTagName("*")].map(x=>x.tagName))