我正在尝试从其中一门课程中重新创建一些实践。它即将从一个 UL 中删除一个 li-item 并将其附加到另一个 UL。
当我按照以下方式编写代码时,一切正常
var removeMeandAppendMe = function() {
var parentLi = this.parentNode;
var goneElement = incompleList.removeChild(parentLi);
compleList.appendChild(goneElement);
};
var li = incompleList.getElementsByTagName('li');
for (var i = 0; i < incompleList.children.length; i++) {
var link = li[i];
var liCheckArray = link.getElementsByTagName('input');
var liCheck = liCheckArray[0];
liCheck.onchange = removeMeandAppendMe;
}
当我将代码更改为以下内容时,出现错误“无法在‘Node’上执行‘removeChild’:参数 1 不是‘Node’类型”。
function removeMeandAppendMe(fromList, toList) {
var parentLi = this.parentNode;
var goneElement = fromList.removeChild(parentLi);
toList.appendChild(goneElement);
}
var li = incompleList.getElementsByTagName('li');
for (var i = 0; i < incompleList.children.length; i++) {
var link = li[i];
var liCheckArray = link.getElementsByTagName('input');
var liCheck = liCheckArray[0];
liCheck.onchange = removeMeandAppendMe(incompleList, compleList);
}
令我困扰的是,当我的 removeMeandAppendMe 函数没有参数且无法使用参数时,代码运行良好。谁能告诉我为什么以及我的错误在哪里?谢谢。
(我知道这里讨论的模糊问题:Failed to execute 'removeChild' on 'Node')
首先,正如 Pointy 提到的,您确实需要将对
RemoveMeandAppendMe(incompleList, compleList)
的调用包装在一个匿名函数中,这样它就不会被过早调用。
考虑到这一点,您收到此错误是因为
this
的值是每个函数调用的情况。当调用 RemoveMeandAppendMe()
时,this
是一个 HTMLInputElement 对象,但是当调用 RemoveMeandAppendMe(incompleList, compleList)
时,this
是 Window 对象,所以 this.parentNode
是 undefined
(因此“不是‘节点’类型”),这就是您看到该错误消息的原因)。
这个问题有很多微妙之处:
this
指的是什么,以及如何处理不同的“功能”声明(很多讨论here)。只是改变 RemoveMeandAppendMe(incompleList, compleList)
的声明方式也不能解决问题。
在某种程度上,您的问题归结为“为什么
this
指的是参数化函数调用的 Window 对象,而不是非参数化函数调用的 HTMLInputElement 对象?”我相信在这种情况下,这是因为,当我们将参数化函数调用的调用包装在匿名函数中时(如:liCheck.onchange = function(){removeMeandAppendMe(incompleList, compleList);};
),removeMeandAppendMe
没有“本地”所有者,因此该函数的所有权默认为全局对象 Window(reference)。
要解决此问题,您可以将
this
传递给 removeMeandAppendMe
的调用,其中 this
将引用复选框,然后将其用作该参数化函数中的变量。我已经把所有这些都放在你的 fiddle 中,可以通过评论/取消评论不同的东西来玩这些东西。希望这有帮助。