2010-05-23 53 views
1

问题是这样的:只是一个小问题关于JavaScript的BOM问题

创建一个包含多个链接的页面。然后编写触发窗口onload事件的代码,在页面上显示每个链接的href。

这是我的解决方案

<html> 
<body language="Javascript" onload="displayLink()"> 
<a href="http://www.google.com/">First link</a> 
<a href="http://www.yahoo.com/">Second link</a> 
<a href="http://www.msn.com/">Third link</a> 

<script type="text/javascript" language="Javascript"> 
function displayLink() 
{ 
for(var i = 0;document.links[i];i++) 
{ 
alert(document.links[i].href); 
} 
} 
</script> 

</body> 
</html> 

这是书

<html> 
<head> 
<script language=”JavaScript” type=”text/javascript”> 
function displayLinks() 
{ 
var linksCounter; 
for (linksCounter = 0; linksCounter < document.links.length; linksCounter++) 
{ 
    alert(document.links[linksCounter].href); 
} 
} 
</script> 
</head> 
<body onload=”displayLinks()”> 
<A href=”link0.htm” >Link 0</A> 
<A href=”link1.htm”>Link 2</A> 
<A href=”link2.htm”>Link 2</A> 
</body> 
</html> 

提供的答案在我进入关于如何检查用户的浏览器版的javascript教程或模型,我正在使用与示例相同的方法,通过访问links数组的length属性,但是在阅读完本教程后,我发现我也可以使用这种替代方法,只有在document.links[i]返回有效值时才使用测试条件将评估为真的方法,所以我的代码是使用有效值写入的方法??如果不是这样,关于如何编写更好的代码的任何评论?纠正我,如果我错了,我听到一些人说:“一个好的代码不仅仅评估它是否有效,而是评估速度条款,理解代码的能力,并且可能会让别人轻松理解代码“。是真的吗?

+0

是的,那是真的。 – 2010-05-23 08:01:43

回答

5

一般来说,当循环访问数组时,您希望使用它的length属性作为本书的解决方案。你的解决方案在这种情况下也应该很好,但它有一个弱点:对于数组中的一个入口是0,null,0 undefinedfalse,它们都是“假”值并且所以即使你不在数组的末尾,document.links[i]也可能是假的。

例子:

var index, a; 
a = [3, 2, 1, 0, -1, -2]; 
for (index = 0; a[index]; ++index) { 
    alert(a[index]); 
} 

这将提醒321,但是随即停止。对比:

var index, a; 
a = [3, 2, 1, 0, -1, -2]; 
for (index = 0; index < a.length; ++index) { 
    alert(a[index]); 
} 

...这将提醒3210-1-2

您可能会看到如下所示的代码:for (index in a)。一般来说,不要用它来循环数组索引,它是基于对什么for..in做什么的误解。 (更多关于下面的内容)

(在新的第5版规范中增加了另外一种循环数组条目的新方法:forEach函数。给它一个函数,并为每个函数调用它数组中的元素。Details in this other answer.。可悲的是,IE8不支持它,但它的事情之一,可以“匀”   —搜索“ES5垫片”的多个选项。)

当得知阵列,知道Javascript数组与其他大多数语言中的数组非常相似,这一点很重要。首先,他们不是(一定)阵列;实际上,它们只是普通的Javascript对象,并增加了一些特殊功能。 Javascript对象是属性映射,它们将键映射到值。例如:

var obj = {foo: 1}; 

obj对象映射的关键"foo"(字符串)值1。您可以通过在代码中使用文字名称或使用[]和字符串来访问该属性。当然,如果你在做后者,你可以使用任何字符串(文字或从变量或从表达式等)。因此,所有这些都有相同的结果:

x = obj.foo; 
x = obj["foo"]; 
name = "foo"; 
x = obj[name]; 
name = "o"; 
x = obj["f" + name + name]; 

...你明白了;只要你在[]中使用的是一个字符串,你可以使用该键查找值。但使用Javascript也确实隐含的强制,所以此工程:

var obj = {"1": "one"}; 
alert(obj[1]); // alerts "one" 

在那里,我已经制定了一个名为"1"到值"one"属性。但后来我用obj[1]来查找它,使用数字而不是字符串。没关系,解释器会把它变成一个字符串,然后做关键字查找。

这与数组有什么关系?这:数组索引只是属性名称。 JavaScript数组是一个正常的对象,键映射到值,具有这些特殊功能:

  • 每当你的名字可以被解释为数字的属性,如果这个数字比目前的最高指数出现较大的在数组中,length属性已更改。所以:

    var a = ["zero"]; 
    alert(a.length); // alerts 1 
    a[3] = "three"; 
    alert(a.length); // alerts 4, because the max index is now 3 
    
  • 每当你length,如果有与具有大于或等于新的长度值数字名称的属性,这些属性是从对象中删除。

    var a = ["zero", "one", "two", "three"]; 
    alert(a[3]); // alerts "three" 
    a.length = 3; 
    alert(a[3]); // alerts "undefined", the "3" property has been deleted 
          // only the "0", "1", and "2" properties remain 
    
  • 他们有他们从Array.prototype,像joinsplice继承功能的各种属性。

就是这样。完全不像C,C++,Java或其他大多数语言中的数组。

由于磁盘阵列的只是一对夫妇的额外功能的对象,你可以把阵列等,非数字属性,如果你想:

var a = ["zero", "one", "two"]; 
a.foo = "bar"; 
alert(a[1]);  // alerts "one", 1 is implicitly coerced to "1" 
alert(a["1"]); // alerts "one" 
alert(a.foo);  // alerts "bar" 
alert(a["foo"]); // alerts "bar" 

而这正是该for..in事情打破了:因为for..in不通过数组索引循环,它遍历属性名称:

var a, name; 
a = [1, 2, 3]; 
a.foo = "bar"; 
for (name in a) { 
    alert(name); 
} 

这提醒"1""2""3""foo"(没有特别的顺序)。你可以看到,如果你认为它只是数组索引,你会遇到麻烦!您可以用它来循环数组索引,但它更复杂,比它的价值:

for (name in a) { 
    if (String(Number(name)) === name && a.hasOwnProperty(name)) { 
     alert(name); 
    } 
} 

,首先检查是否属性名称是一个数字,然后检查该财产的定义上a本身,而不是Array.prototype(请记住,数组继承了Array原型的属性)。 (公平地说,后面的检查可能不是那么重要;如果有人向Array原型添加数字命名的属性,他们会做一件非常糟糕的事情。)

+1

+1我发表了这个问题,但我宁愿喜欢这个答案。这是我读过的最好的解释之一(超过15年)。 – GitaarLAB 2013-12-10 04:09:04

0

是的,它是确保代码不仅可以工作,而且易于理解。这就是所谓的可管理性,是编写优秀代码的一个非常重要的方面。

让我们来看看在你的代码的一些分歧和一些问题和提供答案:

  • 你缺少的HTML文档中head部分。这是文档必须是有效的HTML。

  • 提供的答案缺少head中的title标记,这也是必需的。

  • Javascript标记应该最好在文档的head部分。它的作用是在主体中添加脚本标签,但这是非标准的,因此如果没有特定的原因,应该避免使用脚本标签。

  • 脚本标记有一个language属性,它已被弃用了很长时间,它只需要type属性。

  • 您正在使用变量i进行循环,这是一个众所周知的惯例。为变量提供描述性名称是良好编码的另一方面,但这并不意味着每个变量都必须有长名称。一些用于容易识别目的的变量,如循环计数器,可以使用短名称。

  • 检查集合的长度比检查有效值要好,它更适合您实际想要执行的操作。在这种情况下检查一个有效的值是有效的,但是如果你有一个可以包含空值的集合,那么循环将停在第一个空值处,缩短循环。

因此,与添加了一些有用的东西像一个DOCTYPE声明(使页面呈现在标准模式而不是怪异模式)和页面的内容块的标签,我会建议代码查找像这样:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
<html> 
<head> 
    <title>Links test</title> 

    <script type="text/javascript"> 

    function displayLink() { 
    for(var i = 0; i < document.links.length; i++) { 
     alert(document.links[i].href); 
    } 
    } 

    </script> 

</head> 
<body onload="displayLink();"> 

    <div> 
    <a href="http://www.google.com/">First link</a> 
    <a href="http://www.yahoo.com/">Second link</a> 
    <a href="http://www.msn.com/">Third link</a> 
    </div> 

</body> 
</html> 
+1

感谢这里的许多专家!!!!我无法抗拒自己说你们真的很热情和乐于助人!!!!我会仔细阅读后面给出的意见和建议,并就此做出艰难的决定最好的答案,虽然我觉得每一个答案都很好!!!!再次谢谢 – caramel1995 2010-05-23 09:04:08