Javascript:无法在'Node'上执行'removeChild':参数1不是'Node'类型

时间:2015-07-07 20:06:25

标签: javascript removechild

我正在尝试从其中一门课程中重新创建一些练习。它即将从UL中移除一件物品并将其附加到另一个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;
}

当我将代码更改为以下内容时,我在“节点”上收到错误“无法执行'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'

1 个答案:

答案 0 :(得分:0)

First, as Pointy mentioned, you do need to wrap your call to RemoveMeandAppendMe(incompleList, compleList) in an anonymous function so that it is not invoked prematurely.

Taking that into account, you are receiving this error because of what the value of this is the case of each function invocation. When calling RemoveMeandAppendMe(), this is an HTMLInputElement object, but when calling RemoveMeandAppendMe(incompleList, compleList), this is the Window object, and so this.parentNode is undefined (and thus "not of type 'Node'", which is why you're seeing that error message).

There are a lot of subtleties to this question: what this refers to, and also how different 'function' declarations are treated (lots of discussion here). Just changing the way RemoveMeandAppendMe(incompleList, compleList) is declared doesn't resolve the issue either.

In a way, your question boils down to "Why does this refer to the Window object for the parameterized function call, but an HTMLInputElement object for the non-parameterized function call?" I believe that in this case, this is because, when we wrap the invocation of the parameterized function call in an anonymous function (like so: liCheck.onchange = function(){removeMeandAppendMe(incompleList, compleList);};), removeMeandAppendMe has no 'local' owner, so the ownership of this function defaults to the global object, Window (reference).

To fix this, you can pass in this to the invocation of removeMeandAppendMe, where this will refer to the checkbox, and then use it as a variable within that parameterized function. I've put all of this in your fiddle where things can be played with by commenting/uncommenting different things. Hope this helped.