2012-05-15 45 views
100

我知道這是不好的做法。如果可能的話,不要這樣寫代碼。內聯Javascript(HTML)如何工作?

當然,我們總是會發現自己處於一個巧妙的內聯Javascript片段可以快速解決問題的情況。至於我可以告訴這個

<a href="#" onclick="alert('Hi')">Click Me</a> 

在功能上一樣

我追求在充分了解發生了什麼利益這個查詢(以及潛在的陷阱),當這樣的事情是寫

<script type="text/javascript"> 
    $(function(){ // I use jQuery in this example 
     document.getElementById('click_me').onclick = 
      function() { alert('Hi'); }; 
    }); 
</script> 
<a href="#" id="click_me">Click Me</a> 

從這裏推斷,似乎分配給屬性onclick的字符串被插入到分配給該元素的點擊處理程序的匿名函數中。這是真的嗎?

因爲我開始做這樣的事情:

<a href="#" onclick="$(this).next().fadeIn(); return false;">Display my next sibling</a> <!-- Return false in handler so as not to scroll to top of page! --> 

其中一期工程。但我不知道這是多少破解。它看起來可疑,因爲沒有明顯的功能正在返回!

你可能會問,你爲什麼這麼做,史蒂夫?內聯JS是不好的做法!

好吧,說實話,我已經厭倦了編輯代碼的三個不同部分來修改頁面的一個部分,特別是當我只是做一些原型來看它是否可以工作時。這是非常容易,有時甚至是有意義的,特別是與這個HTML元素相關的代碼被定義爲之內:當我2分鐘後決定這是一個可怕的,可怕的想法時,我可以將整個div或者其他),並且我沒有在頁面的其餘部分懸掛一堆神祕的JS和CSS cruft,減慢渲染速度。這與引用的局部性的概念相似,但是我們正在查看錯誤和代碼膨脹,而不是緩存未命中。

+3

你是對的,這是一個匿名函數。 – bhamlin

+1

您需要在DOMready事件上掛鉤'#click_me'的查詢,或將該腳本放置在該節點之後。 – Bergi

+1

在控制檯中,執行'document.getElementById(「click_me」)。onclick;'。或者提醒它。你會看到它在一個函數中。 –

回答

76

您已經知道它幾乎正確,但您沒有考慮提供給內聯代碼的this值。

<a href="#" onclick="alert(this)">Click Me</a> 

是實際上更接近:

<a href="#" id="click_me">Click Me</a> 
<script type="text/javascript"> 
document.getElementById('click_me').addEventListener("click", function(event) { 
    (function(event) { 
     alert(this); 
    }).call(document.getElementById('click_me'), event); 
}); 
</script> 

內聯的事件處理程序設置this等於事件的目標。

+7

腳本必須在標籤後面,否則標籤在執行時不存在 - 我建議改變你的答案以反映這一點。 – undefined

3

它看起來很可疑,因爲沒有明顯的功能正在返回!

它是一個匿名函數,已被附加到對象的單擊事件。

你爲什麼要這樣做,史蒂夫?

究竟爲什麼你DOI .....啊請不要介意,因爲你所提到的,其實是廣泛採用的是不好的做法:)

8

,當你有瀏覽器做什麼

<a onclick="alert('Hi');" ... > 

是有效設置的「點擊」的東西的實際價值,如:

new Function("event", "alert('Hi');"); 

也就是說,它會創建一個預期的「事件」啪功能rameter。 (嗯,IE並沒有,它更像是一個簡單的匿名函數。)

+1

啊。所以我實際上可以使用變量'event'從我的內聯JS代碼片段中檢索事件(以及通過'event.target'的原始元素)!涼。 –

+1

IE真的不會傳遞'event'參數,但是如果您在這個匿名函數內部使用'event',IE會將它理解爲實際的事件對象。由於匿名函數在IE中被設置爲'window'對象的屬性,因此它會將其視爲'window.event'。 – PanterA

+0

@rbyte是的,這是正確的。 – Pointy

4

回答你的問題的最好方法是see它的行動。

<a id="test" onclick="alert('test')"> test </a> ​ 

在JS

var test = document.getElementById('test'); 
console.log(test.onclick); 

正如您在console,看看你是否正在使用Chrome它打印與傳入的事件對象的匿名函數,雖然它在IE有點不同。

function onclick(event) { 
    alert('test') 
} 

我同意你關於內聯事件處理程序的一些觀點。是的,它們很容易編寫,但我不同意你在多個地方更改代碼的觀點,如果你構建好代碼,你不需要這樣做。

+0

我覺得像''對於原型設計來說非常合適。你現在想要測試一些需要用戶交互的東西,而且你稍後將會刪除它。爲什麼要在整個地方編寫額外的代碼? –

+0

這不是額外的代碼,只是一個額外的匿名函數。它並不是全部,它實際上都在一個地方,在腳本標籤中。 –

+0

我不確定我們是否有「構建好代碼」的相同想法。如果你將UI綁定到你的核心功能實際存在的地方,那麼在我看來,這似乎是一種更糟糕的耦合安排,而不僅僅是將它們綁定到UI中。我通常保持所有的UI綁定的東西與核心的東西分開,我感覺OP也可能...... –

3

試試這個控制檯:

var div = document.createElement('div'); 

div.setAttribute('onclick', 'alert(event)'); 

div.onclick 

在Chrome中,它顯示了這一點:

function onclick(event) { 
    alert(event) 
} 

...和div.onclick非標準name屬性爲"onclick"

因此,無論這是匿名取決於您的「匿名」的定義。喜歡的東西var foo = new Function(),其中foo.name是一個空字符串比較,並foo.toString()會產生類似

function anonymous() { 

} 
+0

這開始是對Pointy的回答發表評論,但實際上並沒有作爲評論。我認爲他的確是這裏最好的答案。 –

5

似乎有很多不好的做法被周圍的事件處理程序拋出屬性。糟糕的做法是不知道和使用最合適的可用功能。事件屬性完全符合W3C文檔標準,對他們沒有任何不好的做法。這與放置內聯樣式沒有什麼不同,這也是W3C記錄的,並且有時候會很有用。無論你是否將它放在腳本標記中,它都會以相同的方式解釋。

https://www.w3.org/TR/html5/webappapis.html#event-handler-idl-attributes

+1

是的,我傾向於同意,我甚至提供了合理的「理由」,說明爲什麼在特定情況下使用內聯代碼可能是合理的。但事實是,當一個應用程序(網絡應用程序或其他應用程序)變得特定的複雜性(並且這通常不需要太多時間或工作就能達到),而只有少量*代碼片段*散佈有關HTML *佈局*從可維護性的角度來看可能在架構上不健全。例如,甚至開始直接將JS編碼到HTML文件中,例如,人們正在誘惑狹窄的spaghetti斜坡。 –

+1

這是一個適當的有效論據,反對,我同意。我通常不會添加內聯腳本,也不會爲此類添加樣式。但人們有不同的口味。很多例如喜歡在主體部分添加腳本和樣式標籤,我無法忍受它。但它是有效的,有些人喜歡它。對某些人來說,像「壞習慣/ spaghettification」這樣的接縫,對其他人來說是「良好的實踐/結構」。 –