理解& # 39;parentNode& # 39;未定义的错误

Understanding 'parentNode' of undefined error

本文关键字:错误 parentNode 理解 未定义      更新时间:2023-09-26

我正在通过为自己设置小练习来练习基本的JS技能。在这个例子中,我在一个div中有一个<a> s的列表。练习的目的是将每个<a>包装在一个div中。在这个例子中我使用replaceChild

奇怪的是(至少对我来说),该脚本对前三个链接有效,但之后抛出一个错误:

Uncaught TypeError: Cannot read property 'parentNode' of undefined

我不知道为什么脚本部分工作。有人能看出我哪里做错了吗?下面是我使用的代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
div div {padding: 10px; background: #e7e7e7; margin: 5px;}
</style>
</head>
<body>
<div>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
</div>
<script>
var links = document.getElementsByTagName("a");
for (var i=0, ii=links.length; i<ii; i++) 
{
    var container = document.createElement("div");
    links[i].parentNode.replaceChild(container, links[i]);
    container.appendChild(links[i]);
}
</script>
</body>
</html>

,这是一个在线版本:http://codepen.io/anon/pen/Lpuky

我已经尝试了我所知道的几种调试技术,并阅读了有关此错误消息的内容,但还没有找出这里的问题所在。我觉得很有趣,6个链接中有3个有效。

集合linksNodeList,为live

由于您正在替换它们,它们将从集合中消失,并且我们对它们的索引不再指向任何内容。

您在迭代节点列表时正在修改它。使用Array slice方法复制列表:

var linksCopy = Array.prototype.slice.call(links);
for (var i=0; i<linksCopy.length; i++) 
{
    var container = document.createElement("div");
    linksCopy[i].parentNode.replaceChild(container, linksCopy[i]);
    container.appendChild(linksCopy[i]);
}

关于您自己的后续回答:如果您的目标只是找到将<a> s包装在<div> s中的最简单方法,而不是使用createElement, replaceChildappendChild或任何其他方法进行练习,那么这将是:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Demo</title>
<style>
div div {
    padding: 10px;
    background: #e7e7e7;
    margin: 5px;
}
</style>
</head>
<body>
    <div>
        <a href="#">link</a>
        <a href="#">link</a>
        <a href="#">link</a>
        <a href="#">link</a>
        <a href="#">link</a>
        <a href="#">link</a>
    </div>
<script>
var links = document.querySelectorAll("a");
for (var i=0; i<links.length; i++) {
    links[i].outerHTML = '<div>'+links[i].outerHTML+'</div>';
}
</script>
</body>
</html>


现场演示在这里:http://jsbin.com/jasoho/1/edit?html,output。outerHTML方法的另一个优点是它不会改变nodeList。所以你也可以用getElementsByTagName代替querySelectorAll

作为一个后续,我经常听说querySelectorAll()是不同的,因为它返回一个静态的Nodelist而不是一个数组,所以我认为这可能会派上用场,它确实是:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
div div {padding: 10px; background: #e7e7e7; margin: 5px;}
</style>
</head>
<body>
<div>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
</div>
<script>
var links = document.querySelectorAll("a");
for (var i=0, ii=links.length; i<ii; i++) 
{
    var container = document.createElement("div");
    links[i].parentNode.replaceChild(container, links[i]);
    container.appendChild(links[i]);
}
</script>
</body>
</html>

另外,Array.prototype.slice.call(links)的替代方案是[].slice.call(links):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
div div {padding: 10px; background: #e7e7e7; margin: 5px;}
</style>
</head>
<body>
<div>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
</div>
<script>
var links = document.getElementsByTagName("a");
var linksCopy = [].slice.call(links);
for (var i=0; i<linksCopy.length; i++) 
{
    var container = document.createElement("div");
    linksCopy[i].parentNode.replaceChild(container, linksCopy[i]);
    container.appendChild(linksCopy[i]);
}
</script>
</body>
</html>

另一个选项是使用[].forEach.call():

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
div div {padding: 10px; background: #e7e7e7; margin: 5px;}
</style>
</head>
<body>
<div>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
</div>
<script>
[].forEach.call(document.querySelectorAll('a'), function(el) {
var container = document.createElement("div");
el.parentNode.replaceChild(container, el);
container.appendChild(el);
});
</script>
</body>
</html>

是另一个选项,使用Array.from():

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
div div {padding: 10px; background: #e7e7e7; margin: 5px;}
</style>
</head>
<body>
<div>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
    <a href="">link</a>
</div>
<script>
var links = document.getElementsByTagName("a");
var linksCopy = Array.from(links);
for (var i=0; i<linksCopy.length; i++)
{
    var container = document.createElement("div");
    linksCopy[i].parentNode.replaceChild(container, linksCopy[i]);
    container.appendChild(linksCopy[i]);
}
</script>
</body>
</html>