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

car*_*995 1 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>
Run Code Online (Sandbox Code Playgroud)

这是本书提供的答案

<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>
Run Code Online (Sandbox Code Playgroud)

在我进入关于如何检查用户浏览器版本或模型的javascript教程之前,我使用与示例相同的方法,通过访问循环lengthlinks数组属性,但是在我阅读完本教程之后,我发现了我也可以使用这种替代方法,通过使用只有在document.links[i]返回有效值时测试条件将评估为true的方法,我的代码是否使用有效方法编写?如果不是,则有关如何编写的任何注释一个更好的代码??纠正我,如果我错了,我听到一些人说"一个好的代码不仅仅评估它是否有效,而是在速度,理解代码的能力,以及可能可以让其他人轻松地理解代码".这是真的吗?

T.J*_*der 5

通常,在循环遍历数组时,您希望使用其length属性作为本书的解决方案.您的解决方案应该是在这个就好了特殊情况为好,但它有一个缺点:这是完全有效的阵列中的一个条目是0,null,undefined,或false,所有这一切都是"falsey"值,因此document.links[i]可能是假的,即使你不在阵列的最后.

例:

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

这会提醒3,21,但是随即停止.相比于:

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

...这将提醒3,2,1,0,-1,和-2.

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

(还有另一种循环数组条目的新方法已添加到新的第5版规范:forEach函数.你给它一个函数,它为数组中的每个元素调用它.详细说明在另一个答案中.可悲的是,IE8不支持它,但它是可以"填充"的东西之一 - 为多个选项搜索"es5 shim".)

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

var obj = {foo: 1};
Run Code Online (Sandbox Code Playgroud)

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

x = obj.foo;
x = obj["foo"];
name = "foo";
x = obj[name];
name = "o";
x = obj["f" + name + name];
Run Code Online (Sandbox Code Playgroud)

......你明白了; 只要您在[]评估字符串中使用的内容,您就可以使用该键查找该值.但是Javascript也会进行隐式强制,所以这有效:

var obj = {"1": "one"};
alert(obj[1]); // alerts "one"
Run Code Online (Sandbox Code Playgroud)

在那里,我已经映射了一个名为"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
    
    Run Code Online (Sandbox Code Playgroud)
  • 无论何时设置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
    
    Run Code Online (Sandbox Code Playgroud)
  • 它们具有从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"
Run Code Online (Sandbox Code Playgroud)

而这其中for..in的事情打破了:因为for..in确实没有通过数组索引循环,它遍历属性名称:

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

这提醒"1","2","3",和"foo"(排名不分先后).你可以看到如果你假设它只是数组索引,你就会遇到麻烦!您可以使用它来循环数组索引,但它比它的价值更复杂:

for (name in a) {
    if (String(Number(name)) === name && a.hasOwnProperty(name)) {
        alert(name);
    }
}
Run Code Online (Sandbox Code Playgroud)

首先检查属性名称是否为数字,然后检查属性是否已定义a,而不是Array.prototype(请记住,数组从Array原型继承属性).(公平地说,后一种检查可能并不是那么重要;如果有人在数组原型中添加了数字命名的属性,那么他们就会做很糟糕的事情(tm).)