成功覆盖document.getElementsByTagName,但不成功覆盖Element.prototype.getElementsByTagName

时间:2014-01-15 04:49:33

标签: javascript prototype

我正在尝试创建一个覆盖getElementsByTagName()方法的程序。为此,我尝试覆盖document.getElementsByTagName()案例1 )和[x].getElementsByTagName()案例2 ),其中[x]是任何DOM元素对象。 问题:我能够成功覆盖案例1 ,但不能案例2

这是我采用的方法(JSFiddle - 我简化了代码以便更容易理解)。首先,为了覆盖案例1 ,我覆盖了document.getElementsByTagName(),以便调用此方法会提醒传递给它的标记名称,如下所示:

//Override document.getElementsByTagName
document.oldGetElementsByTagName = document.getElementsByTagName;
document.getElementsByTagName = function(tagName) {
    var theElems = document.oldGetElementsByTagName(tagName);
    alert("The Tag: " + tagName);
    return theElems;
}

接下来,为了处理案例2 ,我使用了类似的方法来覆盖Element.prototype.getElementsByTagName(),如下所示:

//Override Element.prototype.getElementsByTagName
Element.prototype.oldGetElementsByTagName = Element.prototype.getElementsByTagName;
Element.prototype.getElementsByTagName = function(tagName) {
    var theElems = Element.prototype.oldGetElementsByTagName(tagName);
    alert("The Tag: " + tagName);
    return theElems;
}

现在,让我们说DOM包含以下内容:

<ul id="something">
    <li>1</li>
    <li>2</li>
</ul>

要测试被覆盖的document.getElementsByTagName(),请执行以下操作...

try {
    var items = document.getElementsByTagName("li"); //Will be successful
}
catch (err) {
    alert("Error: " + err.message);
}

...它会警告标记名称“li”,因此方法覆盖成功。要测试被覆盖的Element.prototype.getElementsByTagName(),将执行以下操作...

try {
    var wrapper = document.getElementById("something");
    var items = wrapper.getElementsByTagName("li"); //Will lead to error
}
catch (err) {
    alert("Error: " + err.message);
}

...但是,在这种情况下,会收到以下错误消息:

Error: 'getElementsByTagName' called on an object that does not implement interface Element.

Element.prototype.getElementsByTagName()的覆盖方法有什么问题?

1 个答案:

答案 0 :(得分:1)

事实证明,我在覆盖方法中使用Element.prototype是不正确的。更具体地说,最重要的方法中的以下代码......

var theElems = Element.prototype.oldGetElementsByTagName(tagName);

......应该替换为以下内容......

var theElems = this.oldGetElementsByTagName(tagName);

查看更新的JSFiddle。从本质上讲(如果我理解正确的话),Element.prototype.oldGetElementsByTagName只是定义了所有oldGetElementsByTagName个对象共有的对象Element,而不是像常规函数调用那样被“调用”(如果你这样做,它将被解释为你在oldGetElementsByTagName()对象上调用Element.prototype