关于javascript BOM问题只是一个小问题

时间:2010-05-23 07:59:59

标签: javascript

问题是:

创建包含多个链接的页面。然后编写在窗口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教程之前,我使用与示例相同的方法,通过访问length数组的links属性进行循环,但是在阅读完本教程之后,我发现我也可以使用这种替代方法,通过使用只有在document.links[i]返回有效值时测试条件将评估为真的方法,我的代码也是如此是使用有效的方法编写的?如果不是,关于如何编写更好的代码的任何评论??如果我错了就纠正我,我听到一些人说“好的代码不仅仅评估是否有效或不是,但就速度而言,能够理解代码,并且可以让其他人轻易地理解代码“。这是真的吗?

2 个答案:

答案 0 :(得分:5)

通常,在循环遍历数组时,您希望使用其length属性作为本书的解决方案。你的解决方案在这个特定的情况下也应该没问题,但它有一个缺点:对于数组中的条目0null,{完全有效{1}}或undefined,所有这些都是“假”值,因此即使您不在数组末尾,false也可能为假。

示例:

document.links[i]

这会提醒var index, a; a = [3, 2, 1, 0, -1, -2]; for (index = 0; a[index]; ++index) { alert(a[index]); } 32,但随后会停止。比较:

1

...会提醒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)所做的误解。 (更多内容见下文。)

(还有另一种循环数组条目的新方法已添加到新的第5版规范:for..in函数。你给它一个函数,它为数组中的每个元素调用它。Details in this other answer.。可悲的是,IE8不支持它,但它是可以“填充”的东西之一 - 为多个选项搜索“es5 shim”。)

在了解数组时,重要的是要知道Javascript数组与大多数其他语言中的数组非常不同。首先,它们根本不是(必然)阵列;实际上,它们只是普通的Javascript对象,并添加了一些特殊功能。 Javascript对象是属性映射,它们将键映射到值。例如:

forEach

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"查找,使用数字而不是字符串。没关系,解释器会把它变成一个字符串给我,然后进行密钥查找。

所有这些与数组有什么关系?这:数组索引只是属性名称。 Javascript数组是将键映射到值的普通对象,具有以下特殊功能:

  • 每当您设置一个名称可以解释为数字的属性时,如果该数字大于数组中当前的最大索引,则会更改obj[1]属性。所以:

    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
  • 它们具有从Array.prototype继承的函数的各种属性,如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 join

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

由于数组只是具有一些额外功能的对象,因此如果您愿意,可以在数组上放置其他非数字属性:

splice

这就是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); } } 本身上定义,而不是Array.prototype(请记住,数组从Array原型继承属性) 。 (公平地说,后一种检查可能并不是那么重要;如果有人在数组原型中添加了数字命名的属性,那么他们正在做一件非常糟糕的事情(tm)。)

答案 1 :(得分:0)

是的,代码确实不仅可以工作,而且易于理解。它被称为可管理性,是编写优秀代码的一个非常重要的方面。

让我们看看代码中的一些差异和一些问题以及提供的答案:

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

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

  • Javascript标记应该最好位于文档的head部分。它可以在正文中使用脚本标记,但这是非标准的,因此如果没有特定的原因,应该避免使用它。

  • 脚本代码的language属性已被弃用多年,只需要type属性。

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

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

所以,通过添加一些有用的东西,比如doctype声明(以标准模式而不是quirks模式进行页面渲染)和页面内容的块标记,我建议代码看起来像这样: / p>

<!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>