从getElementsByTagName()获取属性的最佳方法?

时间:2011-09-20 18:50:30

标签: javascript dom attributes

我正在玩获取link标记的属性,似乎有几种方法可以访问这些属性:

document.getElementsByTagName("link")[0]['media']
document.getElementsByTagName("link")[0].media
document.getElementsByTagName("link")[0].getAttribute('media')
document.getElementsByTagName("link")[0].attributes['media']

接近荒谬的是有多少路径存在于同一数据中。这些方法中的一种远远优于其他方法吗?

4 个答案:

答案 0 :(得分:12)

我会在这种情况下使用.media,因为media确实是link元素的属性。每个都有它的用途:

  • ['media'] :使用方括号表示法检索“media”属性值。如果您在设计时不知道酒店的名称,请使用方括号表示法。例如,迭代属性时。
  • .media检索“media”属性值。我在大多数情况下会使用它。它提供简洁,直接的财产价值。
  • .getAttribute('media')检索“media”属性值。如果希望属性的值不一定是元素的属性,请使用此选项。并非所有属性都是属性,并非所有属性都是属性。
  • .attributes['media']检索“媒体”属性节点。当您需要有关属性的更多信息而不仅仅是它的值时,请使用属性集合。例如,属性名称。您也可以轻松地使用它来获取值,因为.toString()返回值,但如果您想要的只是值,那么这可能是过度的。 attributes集合对iterating the attributes of an element也很有用。

答案 1 :(得分:4)

您要查找的方法称为getElementsByTagName。它返回一个类似数组的元素列表(不是数组)。

请注意,您的上一个示例.attributes['media']不会像其他方法一样返回字符串。它改为返回一个属性节点。

理论上,访问内容的方式应该是等效的,但浏览器错误会导致其他行为。最好使用抽象层(如jQuery这样的库)来获得一致的行为。如果您打算在没有库的情况下进行编程,那么选择取决于您的品味,但我会说通过属性节点进行的操作通常是最安全的。

要添加更多技术细节,尽管不同的方式在大多数情况下以相同的方式返回,但对于不存在的属性,这不一定是正确的。以下面的HTML为例:<a href='test'>。您可以在a test jsFiddle上的另一个浏览器中自己尝试(下面的输出来自Firefox)。

// Get reference to element
var a = document.getElementsByTagName('a')[0];

// Existent attributes
console.log(a.href); // String: http://fiddle.jshell.net/_display/test
console.log(a.getAttribute('href')); // String: test
console.log(a.attributes['href']); // Attribute node: href

请注意,有一次返回绝对URI,另一次返回原始值。

// Existent invalid attributes
console.log(a.other); // undefined
console.log(a.getAttribute('other')); // String: thing
console.log(a.attributes['other']); // Attribute node: other

页面加载中存在的所有内容都会合并到DOM中,但如果无效则无法作为属性使用。

// Inexistent but valid attributes
console.log(a.title); // Empty string
console.log(a.getAttribute('title')); // null
console.log(a.attributes['title']); // undefined

第一个调用返回了属性默认值。然后我们看到null作为不存在属性的标记。最后,我们得到了一个所谓的NamedNodeMap,它类似于数组和对象的混合。将其作为对象访问会得到undefined值。

// Creating attributes
a.setAttribute('title', 'test title');
console.log(a.title); // String: test title
console.log(a.getAttribute('title')); // String: test title
console.log(a.attributes['title']); // Attribute node: title

属性也可以作为属性使用。

// Creating "attributes" by using property
a.rel = 'test rel';
console.log(a.rel); // String: test rel
console.log(a.getAttribute('rel')); // String: test rel
console.log(a.attributes['rel']); // Attribute node: rel

设置有效属性的属性还会在attributes map。

中创建一个条目
// Inexistent invalid attributes
console.log(a.dummyInvention); // undefined
console.log(a.getAttribute('dummyInvention')); // null
console.log(a.attributes['dummyInvention']); // undefined

a上的属性访问,节点映射上的标记返回值和索引访问。

// Creating invalid attributes via setAttribute
a.setAttribute('title2', 'test title2');
console.log(a.title2); // undefined
console.log(a.getAttribute('title2')); // String: test title2
console.log(a.attributes['title2']); // Attribute node: title2

即使属性存在无效但是它不可用作属性,也会创建属性。

// Creating invalid "attributes" via property
a.title3 = 'test title3';
console.log(a.title3); // String: test title3
console.log(a.getAttribute('title3')); // null
console.log(a.attributes['title3']); // undefined

对象a已扩展但DOM未受影响。

// NamedNodeMap of length 4 and indexes other, href, title, rel, title2 (valid attributes or result of setAttribute in order of creation except those from parsing)
console.log(a.attributes);

节点映射仅反映DOM的当前状态。它不知道我们通过a收到的对象getElementsByTagName的扩展名。

重要的是要注意,操纵JavaScript对象不一定会影响DOM。 DOM仅反映解析时可用的内容以及使用DOM方法或属性修改(具有预定义属性)的修改。我希望我没有错过任何重要案例,而且评论已经足够详细,看看会发生什么。

我很感激对最终的NamedNodeMap的评论,因为我想知道Firefox的行为是否正确,从而放弃解析属性的顺序。

答案 2 :(得分:1)

从功能上讲,它们是平等的。

在性能方面,前两个优势是一个重要因素 - 尽管它们都非常快。请参阅this JSPerf test

实际上,前两个更容易阅读,而我个人的偏好是第二个。 (这也是头发更快。)

答案 3 :(得分:0)

前两个选项是相同的。你可以使用其中之一。我个人更喜欢.media版本,因为我觉得它更容易阅读。

最后两个选项取决于getAttribute()setAttribute(),它们在IE中并不总是可靠的。您可以在reference that Matt posted中阅读更多相关内容。因此,我更喜欢所有四种选择中的.media版本,因为它们最可靠,最易读。