Inline Javascript (ใน HTML) ทำงานอย่างไร


129

ฉันรู้ว่านี่เป็นการปฏิบัติที่ไม่ดี อย่าเขียนโค้ดแบบนี้ถ้าเป็นไปได้

แน่นอนว่าเรามักจะพบว่าตัวเองอยู่ในสถานการณ์ที่ตัวอย่าง 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! --> 

ซึ่งได้ผล แต่ฉันไม่รู้ว่าแฮ็คนี้มีค่าแค่ไหน มันดูน่าสงสัยเพราะไม่มีการส่งคืนฟังก์ชันที่ชัดเจน!

คุณอาจถามว่าทำไมคุณถึงทำแบบนี้สตีฟ? Inline JS เป็นการปฏิบัติที่ไม่ดี!

พูดตามตรงว่าฉันเบื่อที่จะแก้ไขโค้ดสามส่วนที่แตกต่างกันเพียงเพื่อแก้ไขส่วนหนึ่งของหน้าโดยเฉพาะอย่างยิ่งเมื่อฉันสร้างต้นแบบบางอย่างเพื่อดูว่าจะใช้งานได้หรือไม่ มันง่ายกว่ามากและบางครั้งก็สมเหตุสมผลที่โค้ดที่เกี่ยวข้องโดยเฉพาะกับองค์ประกอบ HTML นี้จะถูกกำหนดไว้ภายในองค์ประกอบ: เมื่อฉันตัดสินใจ 2 นาทีต่อมาว่านี่เป็นความคิดที่แย่และแย่มากฉันสามารถหา div ทั้งหมดได้ (หรืออะไรก็ได้ ) และฉันไม่มี Cruft JS และ CSS ลึกลับจำนวนหนึ่งห้อยอยู่ในส่วนที่เหลือของหน้าทำให้การเรนเดอร์ช้าลงเล็กน้อย สิ่งนี้คล้ายกับแนวคิดของสถานที่อ้างอิง แต่แทนที่จะคิดถึงแคชเรากำลังดูจุดบกพร่องและการขยายโค้ด


3
คุณถูกต้องมันเป็นฟังก์ชันที่ไม่ระบุตัวตน
bhamlin

1
คุณจะต้องเชื่อมต่อแบบสอบถามสำหรับ#click_meเหตุการณ์ DOMready หรือวางสคริปต์ไว้หลังโหนด
Bergi

1
document.getElementById("click_me").onclick;ในคอนโซลให้ทำ หรือแจ้งเตือน. คุณจะเห็นว่ามันอยู่ในฟังก์ชัน
D. Strout

คำตอบ:


96

คุณทำถูกต้องแล้ว แต่คุณไม่ได้คิด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เท่ากับเป้าหมายของเหตุการณ์ คุณยังสามารถใช้ฟังก์ชันที่ไม่ระบุชื่อในสคริปต์แบบอินไลน์

<a href="#" onclick="(function(){alert(this);})()">Click Me</a>

7
สคริปต์ต้องอยู่หลังแท็กมิฉะนั้นแท็กจะไม่มีอยู่เมื่อเรียกใช้งาน - ฉันขอแนะนำให้เปลี่ยนคำตอบของคุณเพื่อให้สอดคล้องกับสิ่งนี้
undefined

ฉันจะเผยแพร่eventด้วยอินไลน์ได้อย่างไรonclick='myFunction(event)'??
oldboy

9

สิ่งที่เบราว์เซอร์ทำเมื่อคุณมี

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

คือการตั้งค่าที่แท้จริงของ "onclick" ให้มีประสิทธิภาพเช่น:

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

นั่นคือสร้างฟังก์ชันที่คาดว่าจะมีพารามิเตอร์ "เหตุการณ์" (ดี IE ไม่มันเหมือนฟังก์ชันนิรนามธรรมดาธรรมดา ๆ มากกว่า)


2
อา. ดังนั้นฉันจึงสามารถใช้ตัวแปรeventเพื่อดึงเหตุการณ์ (และองค์ประกอบเริ่มต้นจากมันผ่านทางevent.target) จากข้อมูลโค้ด JS แบบอินไลน์ของฉัน! เย็น.
Steven Lu

1
IE ไม่ผ่านeventพารามิเตอร์ แต่ถ้าคุณใช้eventภายในฟังก์ชันที่ไม่ระบุตัวตนนี้ IE จะเข้าใจว่าเป็น Event Object จริง ในฐานะที่เป็นฟังก์ชั่นที่ไม่ระบุชื่อถูกกำหนดให้เป็นทรัพย์สินของwindowวัตถุใน IE window.eventก็จะเห็นว่านี่เป็น
rdleal

8

ดูเหมือนว่าจะมีการปฏิบัติที่ไม่ดีมากมายที่ถูกโยนทิ้งไปรอบ ๆ คุณสมบัติตัวจัดการเหตุการณ์ แนวปฏิบัติที่ไม่ดีคือการไม่รู้และใช้คุณลักษณะที่มีอยู่ในจุดที่เหมาะสม แอตทริบิวต์เหตุการณ์เป็นมาตรฐาน W3C Documented โดยสมบูรณ์และไม่มีการปฏิบัติที่ไม่ดีเกี่ยวกับพวกเขา ไม่ต่างอะไรกับการวางรูปแบบอินไลน์ซึ่งเป็นเอกสาร W3C และสามารถใช้ประโยชน์ได้ในบางครั้ง ไม่ว่าคุณจะวางไว้ในแท็กสคริปต์หรือไม่ก็ตามระบบจะตีความในลักษณะเดียวกัน

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


2
ใช่ฉันมีแนวโน้มที่จะเห็นด้วยและฉันได้ให้ "เหตุผล" ที่สมเหตุสมผลด้วยซ้ำว่าทำไมการใช้โค้ดอินไลน์ประเภทนี้จึงมีเหตุผลในบางสถานการณ์ แต่ความเป็นจริงก็คือว่าเมื่อแอป (app เว็บหรืออื่น ๆ ) ได้รับจะเป็นความซับซ้อนบางอย่าง (และนี่ไม่ได้มักจะใช้เวลามากหรือทำงานเพื่อการเข้าถึง) มีเกร็ดเล็กเกร็ดน้อยของรหัสกระจายเกลื่อนแบบ HTML รูปแบบที่มีแนวโน้มที่จะ ไม่น่ามองทางสถาปัตยกรรมจากมุมมองของการบำรุงรักษา แม้กระทั่งการเริ่มเขียนโค้ด JS โดยตรงภายในไฟล์ HTML ตัวอย่างเช่นสิ่งหนึ่งกำลังดึงดูดความลาดชันของ spaghettification
Steven Lu

1
และนั่นเป็นข้อโต้แย้งที่ถูกต้องซึ่งฉันเห็นด้วย โดยปกติฉันไม่ได้เพิ่มการเขียนสคริปต์แบบอินไลน์หรือกำหนดรูปแบบสำหรับวัสดุนั้นด้วยตัวเอง แต่คนเรามีรสนิยมที่แตกต่างกัน ตัวอย่างเช่นหลายคนต้องการเพิ่มแท็กสคริปต์และสไตล์ในส่วนเนื้อหาฉันทนไม่ได้ แต่ก็ใช้ได้และบางคนก็ชอบ สิ่งที่ตะเข็บชอบbad practice/spaghettificationสำหรับบางคนคือgood practice/structureสำหรับคนอื่น
Daniel B

ฉันดูที่github.com/styled-components/styled-componentsและหากคุณรวมสิ่งนี้เข้ากับการตอบสนองตอนนี้เรามีทุกอย่างที่เกี่ยวข้องกับส่วนประกอบของแอปของคุณที่อยู่ร่วมกัน (หวังว่าจะอยู่อย่างสงบสุข) ในที่เดียว และมันก็ดูไม่น่ากลัวเช่นกัน รู้สึกเหมือนมีความก้าวหน้า ในแง่นี้การติดขัดรูปแบบและโค้ดแบบอินไลน์ลงใน HTML ไม่ใช่วิธีที่ถูกต้อง (จนถึงขณะนี้ดูเหมือนว่าจะเป็นการติดขัดของ HTML และสไตล์ในโค้ด JS)
Steven Lu

5

วิธีที่ดีที่สุดที่จะตอบคำถามของคุณคือการมองเห็นในการกระทำ

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

ใน js

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

ดังที่คุณเห็นในconsoleกรณีที่คุณใช้โครเมี่ยมมันจะพิมพ์ฟังก์ชันที่ไม่ระบุตัวตนพร้อมกับออบเจ็กต์เหตุการณ์ที่ส่งผ่านแม้ว่าจะแตกต่างกันเล็กน้อยใน IE

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

ฉันเห็นด้วยกับบางประเด็นของคุณเกี่ยวกับตัวจัดการเหตุการณ์แบบอินไลน์ ใช่มันเขียนง่าย แต่ฉันไม่เห็นด้วยกับประเด็นของคุณเกี่ยวกับการต้องเปลี่ยนโค้ดในหลาย ๆ ที่ถ้าคุณจัดโครงสร้างโค้ดได้ดีคุณไม่ควรทำเช่นนี้


ฉันคิดว่าบางสิ่งบางอย่าง<button onclick="login()"> test login </button>เหมาะอย่างยิ่งสำหรับการสร้างต้นแบบ คุณต้องการทดสอบบางสิ่งที่ต้องใช้การโต้ตอบกับผู้ใช้ในตอนนี้และคุณจะลบออกในภายหลัง ทำไมต้องเขียนโค้ดพิเศษทั่วทุกที่?
Dagg Nabbit

ไม่ใช่รหัสพิเศษเป็นเพียงฟังก์ชันพิเศษที่ไม่ระบุตัวตน และมันไม่ได้อยู่ที่เดียว แต่จริงๆแล้วทั้งหมดนี้อยู่ในที่เดียวในแท็กสคริปต์
aziz punjani

ฉันไม่แน่ใจว่าเรามีแนวคิดเดียวกันในการ "จัดโครงสร้างโค้ดของคุณให้ดี" หากคุณผูก UI กับ "ฟังก์ชันหลัก" ของคุณในตำแหน่งที่ฟังก์ชันหลักของคุณใช้งานได้จริงดูเหมือนว่าฉันจะเป็นการจัดเรียงการเชื่อมต่อที่แย่กว่าการผูกไว้ใน UI ฉันมักจะเก็บสิ่งที่เชื่อมโยง UI ทั้งหมดแยกจากเนื้อหาหลักและฉันรู้สึกว่า OP อาจ ...
Dagg Nabbit

3

มันดูน่าสงสัยเพราะไม่มีการส่งคืนฟังก์ชันที่ชัดเจน!

เป็นฟังก์ชันที่ไม่ระบุชื่อที่แนบมากับเหตุการณ์การคลิกของวัตถุ

ทำไมคุณถึงทำแบบนี้สตีฟ?

ทำไมคุณถึงอยู่บนโลกนี้ ..... ไม่เป็นไรอย่างที่คุณได้กล่าวมามันเป็นแนวทางปฏิบัติที่ไม่ดีอย่างกว้างขวาง :)


3

ลองสิ่งนี้ในคอนโซล:

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

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

div.onclick

ใน Chrome จะแสดงสิ่งนี้:

function onclick(event) {
  alert(event)
}

... และคุณสมบัติที่ไม่ได้มาตรฐานnameของdiv.onclickคือ"onclick".

ดังนั้นจะไม่ระบุชื่อหรือไม่นั้นขึ้นอยู่กับคำจำกัดความของคุณว่า "ไม่ระบุชื่อ" เปรียบเทียบกับสิ่งที่ต้องการสตริงว่างอยู่var foo = new Function()ที่ไหนfoo.nameและfoo.toString()จะสร้างสิ่งที่ต้องการ

function anonymous() {

}

สิ่งนี้เริ่มจากการแสดงความคิดเห็นเกี่ยวกับคำตอบของ Pointy แต่ไม่ได้เป็นความคิดเห็น ฉันคิดว่าเขาเป็นคำตอบที่ดีที่สุดจริงๆ
Dagg Nabbit
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.