2010-05-23 50 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