目录
- 基本知识
- 一、js 测试笔记:
- 二、在线测试代码:
- 三、js 方法解析:
- 1、理解 HTMLcollection 对象 和 Nodelist 对象的不同之处
- 2、HTMLCollection 对象
- 3、NodeList 对象
- HTMLCollection 与 NodeList 的区别
- 4、返回 HTMLCollection 对象的方法
- 总结
- 测试 HTMLCollection 对象可以使用的方法
- 总结
- 个人特别理解
- 关于灵活运用 HTMLCollection 对象方法应对复杂情况的代码测试
- 5、返回 NodeList 对象的方法
- parentNode
- querySelector()
- querySelectorAll()
- 有趣的测试, HTML 语言被覆盖
- 有趣的测试 1 - 获取子节点 - 有趣的 p 标签
- 有趣的测试 2 - 获取子节点
- 有趣的测试 3 - 获取子节点
- 有趣的测试 4 - 获取子节点
- 参考链接
基本知识
理解 HTML 父节点、兄弟节点、子节点
理解 HTML 对象
理解 HTML DOM (Document Object Model 文档对象模型)大致了解就行,先埋坑
一、js 测试笔记:
- 如果在 js 中,某一段代码突然出错了,js 是不会报错的,所以这里就是非常让人郁闷,你运行时,也就不知道哪里出问题了,和其他的编程语言的调试机制相比,就很难受;
- js 如果在某一段代码出问题时,既不会报错,也不会继续执行下面的代码,但是前面的代码倒是会执行,只是报错之后的所有代码都不会再执行;
- 最最容易出问题的地方在于,有没有加分号
;
这个问题,注意函数的花括号不需要加;
分号,但是但是基本的代码表达式,都是要加;
分号的,否则报错不显示,很坑的,特别注意是英文的分号 ; 而不是中文的;分号
二、在线测试代码:
(找些在线代码编程网站测试,链接:菜鸟教程 js 在线代码编程)
复制过去运行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<p id="demo">muxiu</p>
<p id="demo1">muxiu</p>
<p id="demo2">muxiu</p>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
document.getElementById("demo").innerHTML = obj;
document.getElementById("demo1").innerHTML = obj.parentNode;
document.getElementById("demo2").innerHTML = obj.parentNode.querySelector("p");
}
</script>
</body>
</html>
运行结果:
this 关键字详解
在二、在线代码测试部分,this
关键字用来获取 button
标签对象,button
对象的父节点是 ul
标签,然后获取 ul 标签的第一个标签。
三、js 方法解析:
标签,也叫元素
1、理解 HTMLcollection 对象 和 Nodelist 对象的不同之处
首先,如果要活用获取到的HTML对象,那么就需要理解HTML对象有两种类型的对象,一个是HTMLcollection对象,一个是 Nodelist 对象,这两种对象,非常非常重要,因为我们在使用了不同的方法,获取到的对象,有可能也是不同类型的对象,所以就导致了,我们要使用不同的方法来处理,当然这两种类型的对象,也有部分相似,方法和属性也是有相同类似的,但是但是有一点要注意,要牢记它们不同的对象处理方法,要不然使用了 HTMLcollection对象的处理方法去处理 Nodelist 对象,那么报错常伴如风。
其中 HTMLCollection是比较HTML发展早期的对象模型,只能包含HTML元素,而NodeList是比较新的模型,相比HTMLCollection更加完善,不光有HTML元素,还有text节点和comment。
HTMLCollection 早期就有的接口如
document.getElementsByClassName()
document.getElementsByTagName()
NodeList 比较新的接口如
document.querySelectorAll()
关于NodeList,HTMLCollection和Array的关系,就是长得像,有个别相似的功能,但是是完全不一样的东西。
2、HTMLCollection 对象
MDN上是这么介绍HTMLCollection的:
Note: This interface is called HTMLCollection for historical reasons(before the modern DOM, collections implementing this interface could only have HTML elements as their items).
翻译一下就是:
之所以叫它HTMLCollection是因为某些历史原因,在新一代DOM出现之前,实现HTMLCollection这个接口的集合只包含HTML元素,所以命名为HTMLCollection。
HTMLCollection 对象类似包含 HTML 元素的一个数组。
注意:
- HTMLCollection 不是一个数组!
- HTMLCollection 看起来可能是一个数组,但其实不是。
- 你可以像数组一样,使用索引来获取元素。
- HTMLCollection 无法使用数组的方法: valueOf(), pop(), push(), 或 join()。
3、NodeList 对象
大部分浏览器的querySelectorAll()返回 NodeList 对象。
注意
- 节点列表不是一个数组!
- 节点列表看起来可能是一个数组,但其实不是。你可以像数组一样,使用索引来获取元素。
- 节点列表无法使用
JavaScript
数组的方法:valueOf()
,pop()
,push()
, 或join()
。
HTMLCollection 与 NodeList 的区别
- HTMLCollection是 HTML 元素的集合。(仅包含元素)
- NodeList 是一个文档节点的集合。
- NodeList 与 HTMLCollection 有很多类似的地方。
- NodeList 与 HTMLCollection 都与数组对象有点类似,可以使用索引 (0, 1, 2, 3, 4, …) 来获取元素。
- NodeList 与 HTMLCollection 都有
length
属性。 - HTMLCollection 元素可以通过
name
,id
或索引来获取。 - NodeList 只能通过索引来获取。
- 只有 NodeList 对象有包含属性节点和文本节点。
4、返回 HTMLCollection 对象的方法
获取HTMLCollection
对象元素数组的方法,如 getElementsByClassName()
、getElementsByTagName()
特别特别注意,虽然说是数组,但本质上并不是数组类型的数据,没法调用 JavaScript 数组方法。
语法:(特别需要提到一点是,这里的开头是 document
,但是一般来说,我们需要理解 节点的概念,这里的 document
代表了文档节点,即根节点,这里笔者是这样理解的,有错的地方请留言,所以只要获取了某个元素对象了,那么就可以以这个元素对象,作为一个根节点,继续 .getElementById
.getElementsByClassName()
或 .getElementsByTagName()
)
document.getElementById()
// 本质是 element.getElementById()
document.getElementsByClassName()
// 本质是 element.getElementsByClassName()
document.getElementsByTagName()
// 本质是 element.getElementsByTagName()
在线测试代码:
在线测试网站链接:菜鸟教程在线测试链接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div1">
div1
<div class="div2">
div2
<div class="div3">
div3
</div>
</div>
</div>
<script>
var parent = document.getElementById('div1');
console.log(parent);
parent = document.getElementsByClassName('div2');
console.log(parent);
parent = document.getElementsByTagName('div');
console.log(parent);
</script>
</body>
</html>
运行结果:(点击上面的在线测试网站链接,把代码复制进去,点击运行,然后再按键盘 F12,查看Console 控制台,可以看到结果)
可以看到只有 getElementsByClassName
、getElementsByTagName
这两个方法返回的时 HTMLCollection
对象,而getElementById
并不是一个HTMLCollection
对象,而是返回了一个HTML元素对象。
一个非常奇妙的一点是 getElementsByName()
,返回的竟然不是 HTMLCollection
对象,如下所示:(先埋坑,后面讲)
总结
仅仅返回一个元素对象的方法,有document.getElementById
、document.documentElement
、document.body
测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul id="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementById('menu');
console.log(parent);
parent = document.body;
console.log(parent);
parent = document.documentElement;
console.log(parent);
</script>
控制台结果:
而只有getElementsByClassName()
、getElementsByTagName()
才能返回 HTMLCollection
的元素对象数组。
测试 HTMLCollection 对象可以使用的方法
测试 getElementById
- innerHTML - 节点(元素)的文本值
- parentNode - 节点(元素)的父节点
- childNodes - 节点(元素)的子节点
- attributes - 节点(元素)的属性节点
在线测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul id="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementById('menu').innerHTML ;
console.log(parent);
var parent = document.getElementById('menu').parentNode ;
console.log(parent);
var parent = document.getElementById('menu').childNodes ;
console.log(parent);
var parent = document.getElementById('menu').attributes ;
console.log(parent);
</script>
</body>
</html>
控制台结果:
测试 getElementsByClassName()
- innerHTML - 节点(元素)的文本值
- parentNode - 节点(元素)的父节点
- childNodes - 节点(元素)的子节点
- attributes - 节点(元素)的属性节点
在线测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul class="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementsByClassName('menu').innerHTML ;
console.log(parent);
var parent = document.getElementsByClassName('menu').parentNode ;
console.log(parent);
var parent = document.getElementsByClassName('menu').childNodes ;
console.log(parent);
var parent = document.getElementsByClassName('menu').attributes ;
console.log(parent);
</script>
</body>
</html>
控制台结果:
可以看到,是没有结果的。
测试 getElementsByTagName
在线测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul class="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementsByTagName('div').innerHTML ;
console.log(parent);
var parent = document.getElementsByTagName('div').parentNode ;
console.log(parent);
var parent = document.getElementsByTagName('div').childNodes ;
console.log(parent);
var parent = document.getElementsByTagName('div').attributes ;
console.log(parent);
</script>
</body>
</html>
控制台结果:
总结
HTMLCollection 对象,其实是一个比较麻烦的数据,常用 元素对象,来获取 HTML DOM 元素对象,这样就可以用参考链接内的所有方法了。之前可能有点混乱,现在理顺了逻辑,总之,如果使用的是 get 开头的方法,是没法用 CSS选择器的方法,去获取 HTML DOM 对象。
除非是
element.querySelector()
:返回匹配指定 CSS 选择器元素的第一个子元素
document.querySelectorAll()
: 返回匹配指定 CSS 选择器元素的所有子元素节点列表
之前是混合了 CSS选择器,弄乱了逻辑,现在清楚了只有这两个方法,才能利用 CSS选择器的方法,查找想要的元素对象,并进行处理。
个人特别理解
element
的 getElementById
方法返回值。
getElementsByClassName
、getElementByTagNmae
方法,可以用数组的方式,for 循环执行
例如:
document.getElementsByClassName("example")[0];
插入 js 代码,最好最好是在 HTML 文件内 body 标签的最后,否则有可能会出现
document.getElementById()获取值打印为null?
这是由于加载顺序问题,html文档是从上往下加载,而不会全部加载后再执行js代码,因此导致get不到节点的信息
解决方案
- 在body标签下引入js文件
- 将js代码加一个onload函数
参考链接:
document.getElementById()获取值打印为null?解决问题
关于灵活运用 HTMLCollection 对象方法应对复杂情况的代码测试
这里要提一句,没法用 CSS 选择器那样去调用,一开始,我也是把它们弄混了,后来发现,异想天开。
下面是之前提到过的,要理解根节点的概念,只有下一级的标签元素对象,就可以使用无限个 .firstElementNode
的方法,去获取下一级的标签元素对象,而 HTML DOM 就是这么挠头,因为是递归的排序,所以有时候在找指定标签对象时,想要获取同级的元素对象,会挺麻烦的,这就得靠 兄弟节点方法了,这是笔者突然间灵感迸发的,请随意。
代码测试1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul id="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementById('menu').getElementsByClassName('display');
console.log(parent);
</script>
</body>
</html>
控制台结果:
代码测试2:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<ul id="menu">
<li>
<a href="#" >菜单选项</a>
<ul class="display">
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
<script>
var parent = document.getElementById('menu').getElementsByTagName('a');
console.log(parent);
</script>
</body>
</html>
控制台结果:
代码测试3:(菜单栏隐藏测试)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<style>
.display{
display:none;
}
</style>
</head>
<body>
<div id="menu">
<ul>
<li>
<a href="#" >菜单选项</a>
<ul>
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
<li>
<a href="#" >菜单选项1</a>
<ul>
<li><a href="#" >选项1</a></li>
<li><a href="#" >选项2</a></li>
</ul>
</li>
</ul>
</div>
<script>
for(var i=1;i<3;i++){
document.getElementById('menu').getElementsByTagName('ul')[i].classList.toggle("display");
}
</script>
</body>
</html>
原图:
效果图:
按数组来查找标签、类对象,是以递归方式查找的,递归查找到了,就当做下一个下标的元素,而不是按照查找子代选择器那样,查找对象的。
参考链接:
5、返回 NodeList 对象的方法
parentNode
parentNode
获取父节点标签对象的方法
querySelector()
语法:
document.querySelector(CSS selectors)
querySelector()
获取指定标签的第一个子节点(标签/元素)对象
特别特别注意:是 document
开头的
querySelectorAll()
语法:
elementList = document.querySelectorAll(selectors);
特别特别注意:是 document
开头的
有趣的测试, HTML 语言被覆盖
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<p id="demo">muxiu0
<li>
<!-- li 标签不和 ul 标签父子关系,也没问题,可以单独使用,类似 p 标签,应该是所有的标签都是这种情况 -->
</li>
</p>
<p id="demo1">muxiu1
<p id="demo3">muxiu3</p>
</p>
<p id="demo2">muxiu2</p>
<li>
<!-- 这里被 li 截断了,但也没问题,每一个 li 标签 都会显示一个黑点,这需要用 css style 样式配置消失 -->
</li>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
// 按钮对象
document.getElementById("demo").innerHTML = obj;
// 按钮对象的父节点
document.getElementById("demo1").innerHTML = obj.parentNode;
// 按钮对象的父节点的第一个标签对象
document.getElementById("demo2").innerHTML = obj.parentNode.querySelector("p") + "id 为 demo2 的 p 标签对象";
//
// document.getElementById("demo1").firstElementChild.innerHTML = "找到了 id 为 demo1 的标签对象,然后利用每一个对象都默认自带的 innerHTML 属性";
document.getElementById("demo3").innerHTML = document.getElementById("demo1").firstElementChild;
}
</script>
</body>
</html>
初始图:
结果图:
很显然 HTML 代码内的 p 标签的元素内容没 innerHTML 给弄没了,所以这个 js 代码毫无作用,如下所示。
毫无作用
有趣的测试 1 - 获取子节点 - 有趣的 p 标签
测试代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<p id="demo">muxiu0
<li>
<!-- li 标签不和 ul 标签父子关系,也没问题,可以单独使用,类似 p 标签,应该是所有的标签都是这种情况 -->
</li>
</p>
<p id="demo1">muxiu1</p>
<p id="demo2">muxiu2</p>
<p id="demo3">muxiu3</p>
<p id="demo4">
<p id="demo5">muxiu4</p>
</p>
<li>
<!-- 这里被 li 截断了,但也没问题,每一个 li 标签 都会显示一个黑点,这需要用 css style 样式配置消失 -->
</li>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
// 按钮对象
document.getElementById("demo").innerHTML = obj;
// 按钮对象的父节点
document.getElementById("demo1").innerHTML = obj.parentNode;
// 按钮对象的父节点的第一个标签对象
document.getElementById("demo2").innerHTML = obj.parentNode.querySelector("p") + "id 为 demo2 的 p 标签对象";
//
// document.getElementById("demo1").firstElementChild.innerHTML = "找到了 id 为 demo1 的标签对象,然后利用每一个对象都默认自带的 innerHTML 属性";
// 获取子节点
document.getElementById("demo3").innerHTML = document.getElementById("demo4").children[0];
document.getElementById("demo5").innerHTML = "demo5";
}
</script>
</body>
</html>
初始图:
结果图:
可以看到一个 undefined
,有点不懂,先埋坑。
有趣的测试 2 - 获取子节点
测试代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<p id="demo">muxiu0
<li>
<!-- li 标签不和 ul 标签父子关系,也没问题,可以单独使用,类似 p 标签,应该是所有的标签都是这种情况 -->
</li>
</p>
<p id="demo1">muxiu1</p>
<p id="demo2">muxiu2</p>
<p id="demo3">muxiu3</p>
<p id="demo4">
<p id="demo5">muxiu4</p>
</p>
<li>
<!-- 这里被 li 截断了,但也没问题,每一个 li 标签 都会显示一个黑点,这需要用 css style 样式配置消失 -->
</li>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
// 按钮对象
document.getElementById("demo").innerHTML = obj;
// 按钮对象的父节点
document.getElementById("demo1").innerHTML = obj.parentNode;
// 按钮对象的父节点的第一个标签对象
document.getElementById("demo2").innerHTML = obj.parentNode.querySelector("p") + "id 为 demo2 的 p 标签对象";
//
// document.getElementById("demo1").firstElementChild.innerHTML = "找到了 id 为 demo1 的标签对象,然后利用每一个对象都默认自带的 innerHTML 属性";
// 获取子节点
document.getElementById("demo3").innerHTML = document.getElementById("demo4").firstElementChild;
document.getElementById("demo5").innerHTML = "demo5";
}
</script>
</body>
</html>
初始图:
结果图:
子节点 demo3
消失了,可以推理出 id
为demo4 p
标签嵌套有问题。
有趣的测试 3 - 获取子节点
测试代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<li id="demo1">
<p id="demo2">muxiu1</p>
</li>
<p id="demo3">
<p id="demo4">muxiu</p>
</p>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
// 获取子节点
document.getElementById("demo2").innerHTML = document.getElementById("demo1").children[0];
document.getElementById("demo4").innerHTML = document.getElementById("demo3").children[0];
}
</script>
</body>
</html>
初始图:
结果图:
从结果图,推理知道,同种标签的嵌套的确有可能出问题
有趣的测试 4 - 获取子节点
测试代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Muxiu Test</title>
</head>
<body>
<h2>JavaScript 对象</h2>
<ul>
<li id="demo1">
<p id="demo2">muxiu1</p>
</li>
<p id="demo3">
<p id="demo4">muxiu2</p>
<a id="demo5">muxiu3</a>
</p>
<button onclick="myfunction(this)">点我后就变帅变靓</button>
</ul>
<script>
function myfunction(obj){
// 获取子节点
document.getElementById("demo2").innerHTML = document.getElementById("demo1").children[0];
document.getElementById("demo4").innerHTML = document.getElementById("demo3").children[0];
document.getElementById("demo5").innerHTML = document.getElementById("demo3").children[1];
}
</script>
</body>
</html>
初始图:
结果图:
这个测试是补充测试,看看加了其他标签在里面,会不会有所不同,看来结果,是一样的,出问题了。