2014-01-15 33 views
0

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

下面是我采取的方法(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()

+0

[不要乱搞DOM](http://perfectionkills.com/whats-wrong-with-extending-the-dom/)!你为什么要覆盖这些方法? – Bergi

+0

@Bergi我实际上并没有创建一个Web应用程序,而是在任何给定的Web应用程序X中执行DOM方法调用的动态分析的DOM统计信息跟踪器(我显然忽略了很多细节,但这是它的要点)。我仍处于开发此统计跟踪器的实验阶段,所以我决定首先使用最简单的实现作为概念证明(尽管这个想法可能会在以后发展)。我认为最简单的实现是通过代理用重写代码来对JS代码进行测试。 –

+0

@Bergi我一路遇到这个问题,并认为分享我找到的解决方案会很有趣。 –

回答

1

事实证明,我在重写方法中不正确地使用了Element.prototype。更具体地说,在压倒一切的方法,下面的代码...

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

...应从以下几...

var theElems = this.oldGetElementsByTagName(tagName); 

更换请参阅更新的JSFiddle。实质上(如果我理解正确),Element.prototype.oldGetElementsByTagName只是简单定义了对象oldGetElementsByTagName对所有对象都通用,并且不打算像在常规函数调用中一样被“调用”(如果这样做,它将被解释为您调用oldGetElementsByTagName()Element.prototype对象上)。

+1

是的,你理解正确。方法语法的替代方法是使用['.call'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)。 – Bergi

+1

是的。您也可以尝试'Element.prototype.oldGetElementsByTagName.call(this,tagName)'。顺便说一句,您无需将旧方法附加到原型上。只需使用一个简单的'var'。 – user123444555621