답변:
둘 다 정확하지만 그중 어느 것도 그 자체로는 "최상의"것은 아니며 개발자가 두 가지 방법을 모두 사용하기로 선택한 이유가있을 수 있습니다.
이벤트 리스너 (addEventListener 및 IE의 attachEvent)
이전 버전의 Internet Explorer는 거의 모든 브라우저와 다르게 자바 스크립트를 구현합니다. 9 미만의 버전 에서는 다음과 같이 attachEvent
[ doc ] 메소드 를 사용합니다 .
element.attachEvent('onclick', function() { /* do stuff here*/ });
대부분의 다른 브라우저 (IE 9 이상 포함)에서는 다음과 같이 addEventListener
[ doc ] 를 사용 합니다.
element.addEventListener('click', function() { /* do stuff here*/ }, false);
이 접근 방식 ( DOM 레벨 2 이벤트 )을 사용하면 이론적으로 무제한의 이벤트를 단일 요소에 첨부 할 수 있습니다. 실질적인 제한 사항은 클라이언트 측 메모리 및 기타 성능 문제로, 각 브라우저마다 다릅니다.
위의 예제는 익명 함수 [ doc ]를 사용하는 것을 나타냅니다 . 함수 참조 [ doc ] 또는 클로저 [ doc ]를 사용하여 이벤트 리스너를 추가 할 수도 있습니다 .
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
또 다른 중요한 특징은 addEventListener
최종 매개 변수인데,이 매개 변수는 리스너가 버블 링 이벤트에 반응하는 방식을 제어합니다 [ doc ]. 예제에서 거짓을 전달했습니다.이 사례는 아마도 95 %의 유스 케이스에 대한 표준입니다. attachEvent
인라인 이벤트를 사용할 때 또는에 해당하는 인수가 없습니다 .
인라인 이벤트 (HTML onclick = ""속성 및 element.onclick)
자바 스크립트를 지원하는 모든 브라우저에서 HTML 코드에서 바로 이벤트 리스너를 인라인으로 배치 할 수 있습니다. 아마 이것을 보았을 것입니다 :
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
대부분의 숙련 된 개발자는이 방법을 피하지만 작업을 완료합니다. 간단하고 직접적입니다. 여기서 처리기 자체는 일종의 익명 함수이지만 클로저 또는 익명 함수를 사용할 수 없으며 범위 제어가 제한됩니다.
다른 방법은 다음과 같습니다.
element.onclick = function () { /*do stuff here */ };
... 범위를 더 많이 제어하고 (HTML 대신 스크립트를 작성하기 때문에) 익명 함수, 함수 참조 및 / 또는 클로저를 사용할 수 있다는 점을 제외하고는 인라인 자바 스크립트와 같습니다.
인라인 이벤트의 중요한 단점은 위에서 설명한 이벤트 리스너와 달리 하나의 인라인 이벤트 만 할당 할 수 있다는 것입니다. 인라인 이벤트는 요소 [ doc ] 의 속성 / 속성으로 저장되므로 덮어 쓸 수 있습니다.
<a>
위의 HTML 예제 를 사용하여 :
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
... 요소를 클릭하면 "Did stuff # 2" 만 표시 됩니다 . 첫 번째로 할당 된 onclick
속성을 두 번째 값으로 덮어 쓰고 원래 인라인 HTML onclick
속성도 덮어 썼습니다 . http://jsfiddle.net/jpgah/ 에서 확인하십시오 .
대체로 인라인 이벤트를 사용하지 마십시오 . 특정 사용 사례가있을 수 있지만 100 % 확실하지 않은 경우 인라인 이벤트를 사용하지 않아야합니다.
현대 자바 스크립트 (Angular 등)
이 답변이 처음 게시되었으므로 Angular와 같은 자바 스크립트 프레임 워크가 훨씬 더 대중화되었습니다. Angular 템플릿에 다음과 같은 코드가 표시됩니다.
<button (click)="doSomething()">Do Something</button>
인라인 이벤트처럼 보이지만 그렇지 않습니다. 이 유형의 템플릿은 뒤에서 이벤트 리스너를 사용하는보다 복잡한 코드로 변환됩니다. 여기에 이벤트에 대해 쓴 모든 내용이 여전히 적용되지만 최소한 하나의 계층으로 인해 핵심에서 제거됩니다. 너트와 볼트를 이해해야하지만 최신 JS 프레임 워크 모범 사례에 이러한 종류의 코드를 템플릿으로 작성하는 경우 인라인 이벤트를 사용하고 있다고 생각하지 마십시오.
어느 것이 최고입니까?
문제는 브라우저 호환성과 필요성의 문제입니다. 요소에 둘 이상의 이벤트를 첨부해야합니까? 미래에 당신은? 확률은 당신입니다. attachEvent 및 addEventListener가 필요합니다. 그렇지 않은 경우 인라인 이벤트는 트릭을 수행하는 것처럼 보일지 모르지만 미래에 대비하는 것이 훨씬 나을 것 같지만 최소한 예상 할 수는 없습니다. JS 기반 이벤트 리스너로 이동해야 할 수도 있으므로 시작하십시오. 인라인 이벤트를 사용하지 마십시오.
jQuery 및 기타 자바 스크립트 프레임 워크는 일반 모델에서 DOM 레벨 2 이벤트의 다양한 브라우저 구현을 캡슐화하므로 반역자로서 IE의 역사에 대해 걱정할 필요없이 브라우저 간 호환 코드를 작성할 수 있습니다. jQuery와 동일한 코드, 모든 크로스 브라우저 및 준비가 완료되었습니다.
$(element).on('click', function () { /* do stuff */ });
그러나이 한 가지에 대해서만 프레임 워크를 사용하지 마십시오. 이전 브라우저를 관리하기 위해 작은 유틸리티를 쉽게 굴릴 수 있습니다.
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
사용해보십시오 : http://jsfiddle.net/bmArj/
보고있는 스크립트가 브라우저의 차이점을 다른 방식으로 고려하지 않는 한 (질문에 표시되지 않은 코드로) 사용 addEventListener
하지 않는 부분 은 9 미만의 IE 버전에서는 작동하지 않습니다.
문서 및 관련 자료
function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}
<< 98 자에서이 문자는 40 % 이상 작습니다!
다른 두 가지 기능이 있는지 확인할 수있는 차이점 :
var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;
h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);
기능 2, 3 및 4는 작동하지만 1은 작동하지 않습니다. 때문입니다 addEventListener
반면, 기존의 이벤트 핸들러를 덮어 쓰지 않습니다 onclick
우선 기존의 onclick = fn
이벤트 핸들러.
물론 다른 중요한 차이점 onclick
은 항상 작동하지만, addEventListener
Internet Explorer 9 이전 버전에서는 작동하지 않는다는 것입니다 . IE <9 에서는 유사한 구문 attachEvent
이 약간 다릅니다.
이 답변에서는 DOM 이벤트 핸들러를 정의하는 세 가지 방법을 설명합니다.
element.addEventListener()
코드 예 :
element.addEventListener()
여러 가지 장점이 있습니다.
element.removeEventListener()
.useCapture
당신은 그것에서 이벤트를 처리할지 여부를 나타내는 매개 변수를 캡처 또는 버블 링 단계를 . addEventListener의 useCapture 속성을 이해할 수 없습니다.를 참조하십시오 ..onevent
DOM 요소의 속성에 이벤트 리스너를 할당하기 때문에 경험이 부족한 많은 JavaScript 프로그래머는 이벤트 이름이 예를 들어 onclick
또는 라고 생각합니다 onload
. 이벤트 이름의 일부 on
가 아닙니다 . 올바른 이벤트 이름은 click
및 load
이며 이벤트 이름이에 전달되는 방식 .addEventListener()
입니다.element.onevent = function() {}
(예를 들어 onclick
, onload
)코드 예 :
이것은 DOM 0에 이벤트 핸들러를 등록하는 방법입니다. 이제 다음과 같은 이유로 권장하지 않습니다.
onevent
특성을 초기 상태 (예 :)로 되돌려 야하기 때문에 지정된 핸들러를 제거하는 것은 직관적이지 않습니다 null
.window.onload
예 window.onload = "test";
:) 오류가 발생하지 않습니다. 코드가 작동하지 않으며 이유를 찾기가 정말 어려울 것입니다. .addEventListener()
그러나 오류가 발생합니다 (적어도 Firefox에서는). TypeError : EventTarget.addEventListener의 Argument 2는 객체가 아닙니다 .onevent
HTML 속성)코드 예 :
와 마찬가지로 element.onevent
이제는 권장하지 않습니다. element.onevent
가지고 있는 문제 외에도 다음과 같은 문제가 있습니다.
Content-Security-Policy
HTTP 헤더를 보내 인라인 스크립트를 차단하고 신뢰할 수있는 도메인의 외부 스크립트 만 허용해야합니다. 콘텐츠 보안 정책 은 어떻게 작동합니까?를 참조하십시오 .addEventListener
여러 이벤트를 추가 할 onclick
수 있지만이 작업을 수행 할 수는 없습니다.onclick
은 HTML
속성 으로 추가 할 수있는 반면에는 요소 addEventListener
내에서만 추가 할 수 있습니다 <script>
.addEventListener
이벤트 전파를 중지시킬 수있는 세 번째 인수를 취할 수 있습니다.둘 다 이벤트를 처리하는 데 사용될 수 있습니다. 그러나 addEventListener
모든 작업을 수행 할 수 있으므로 선호하는 선택이되어야합니다 onclick
. 인라인 onclick
을 HTML 속성으로 사용하지 마십시오 . 이는 자바 스크립트와 HTML을 혼용하기 때문에 잘못된 방법입니다. 코드를 유지 관리하기가 쉽지 않습니다.
onclick
방을 비웃는 것을 두려워 하여 인라인 핸드 렐을 사용하지 않을 것 입니다. 수업은 좋아하는 js-link
, js-form-validation
또는 사용하여 데이터 속성을 data-jspackage="init"
더 나은 결코입니다 ... 어떻게 ofteen 실제로 않는 사용 이벤트 버블 링을? 나는 개인적으로 대상이 실제로 내 요소와 일치하는지 확인하지 않고 임의의 버그로 인해 여러 곳에서 전파를 중단하지 않고 핸들러를 작성할 수 있기를 원합니다.
한 세부 사항은 아직 언급되지 않았습니다 현대 데스크톱 브라우저가 "클릭"으로 다른 버튼 누름을 고려 AddEventListener('click'
하고 onclick
기본적으로.
onclick
를 AddEventListener
클릭하십시오.onclick
발사 에만 왼쪽 클릭에 있지만, AddEventListener
왼쪽, 중간에 화재를 클릭 하고 바로 클릭.또한 스크롤 커서가 포함 된 경우 중간 클릭 동작이 브라우저에서 매우 일치하지 않습니다.
키보드로 선택 가능한 HTML 요소 (예 : input
공간에서 실행되거나 요소를 선택할 때 입력) 와 같은 "클릭"이벤트도 주목할 가치가 있습니다 .
자바 스크립트는 모든 것을 객체로 혼합하는 경향이있어 혼동 될 수 있습니다. 하나의 모든 것은 JavaScript 방식입니다.
본질적으로 onclick은 HTML 속성입니다. 반대로 addEventListener는 HTML 요소를 나타내는 DOM 객체의 메소드입니다.
JavaScript 객체에서 메소드는 단순히 함수를 값으로 가지고 있고 연결된 객체에 대해 작동하는 속성입니다 (예 : 이것을 사용하여).
JavaScript에서 DOM으로 표시되는 HTML 요소는 해당 속성에 해당 속성이 맵핑됩니다.
자바 스크립트가 모든 것을 간접 레이어없이 단일 컨테이너 또는 네임 스페이스에 통합하기 때문에 사람들이 혼란스러워하는 곳입니다.
일반적인 OO 레이아웃 (적어도 속성 / 메소드의 네임 스페이스를 병합하는)에는 다음과 같은 것이있을 수 있습니다.
domElement.addEventListener // Object(Method)
domElement.attributes.onload // Object(Property(Object(Property(String))))
onload에 getter / setter를 사용하거나 속성에 HashMap을 사용할 수있는 것과 같은 변형이 있지만 궁극적으로는 그 모양입니다. JavaScript는 무엇보다도 무엇을 알기 위해 그 간접적 인 계층을 제거했습니다. domElement와 속성을 병합했습니다.
호환성을 제한하는 것이 가장 좋은 방법은 addEventListener를 사용하는 것입니다. 다른 답변에서 나는 근본적인 프로그램상의 차이점보다는 그 점에서의 차이점에 대해 이야기합니다. 기본적으로 이상적인 세상에서는 HTML에서만 * 사용하는 것이 더 중요하지만 더 이상적인 세상에서는 HTML에서 그런 일을해서는 안됩니다.
오늘날 왜 지배적입니까? 작성하는 것이 빠르고 배우기 쉬우 며 작동하는 경향이 있습니다.
HTML에서 온로드의 전체 요점은 먼저 addEventListener 메소드 또는 기능에 대한 액세스 권한을 부여하는 것입니다. JS에서 사용하면 HTML을 직접 적용 할 수있을 때 HTML을 거치게됩니다.
가설 적으로 자신의 속성을 만들 수 있습니다.
$('[myclick]').each(function(i, v) {
v.addEventListener('click', function() {
eval(v.myclick); // eval($(v).attr('myclick'));
});
});
JS가하는 일은 그것과 약간 다릅니다.
생성 된 모든 요소에 대해 다음과 같을 수 있습니다.
element.addEventListener('click', function() {
switch(typeof element.onclick) {
case 'string':eval(element.onclick);break;
case 'function':element.onclick();break;
}
});
실제 구현 세부 사항은 경우에 따라 두 가지를 약간 다르게 만드는 미묘한 변형 범위에 따라 다를 수 있지만 그 핵심입니다.
기본적으로 속성은 모두 문자열이므로 함수를 on 속성에 고정 할 수있는 호환성 해킹 일 것입니다.
MDN 에 따르면 차이점은 다음과 같습니다.
addEventListener :
EventTarget.addEventListener () 메서드는 지정된 EventListener 호환 객체를 호출 된 EventTarget의 지정된 이벤트 유형에 대한 이벤트 리스너 목록에 추가합니다. 이벤트 대상은 문서의 요소, 문서 자체, 창 또는 이벤트를 지원하는 다른 객체 (예 : XMLHttpRequest) 일 수 있습니다.
onclick :
onclick 특성은 현재 요소에서 click 이벤트 핸들러 코드를 리턴합니다. 클릭 이벤트를 사용하여 액션을 트리거 할 때 마우스 나 터치 스크린을 사용하지 않는 사람들이 동일한 액션을 사용할 수 있도록 키 다운 이벤트에 동일한 액션을 추가하는 것도 고려하십시오. 구문 element.onclick = functionRef; 여기서 functionRef는 함수입니다. 종종 다른 곳에서 선언 된 함수의 이름 또는 함수 표현식입니다. 자세한 내용은 "자바 스크립트 안내서 : 기능"을 참조하십시오.
아래 코드에서 볼 수 있듯이 사용상의 구문 차이도 있습니다.
addEventListener :
// Function to change the content of t2
function modifyText() {
var t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
// add event listener to table
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);
onclick :
function initElement() {
var p = document.getElementById("foo");
// NOTE: showAlert(); or showAlert(param); will NOT work here.
// Must be a reference to a function name, not a function call.
p.onclick = showAlert;
};
function showAlert(event) {
alert("onclick Event detected!");
}
브라우저 지원에 대해 너무 걱정하지 않으면 이벤트에서 호출하는 함수에서 'this'참조를 리 바인드하는 방법이 있습니다. 일반적으로 함수가 실행될 때 이벤트를 생성 한 요소를 가리키며, 항상 원하는 것은 아닙니다. 까다로운 부분은 다음 예제와 같이 동시에 동일한 이벤트 리스너를 제거 할 수있는 것입니다. http://jsfiddle.net/roenbaeck/vBYu3/
/*
Testing that the function returned from bind is rereferenceable,
such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
// the following is necessary as calling bind again does
// not return the same function, so instead we replace the
// original function with the one bound to this instance
this.swap = this.swap.bind(this);
this.element = document.createElement('div');
this.element.addEventListener('click', this.swap, false);
document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
element: null,
swap: function() {
// now this function can be properly removed
this.element.removeEventListener('click', this.swap, false);
}
}
위의 코드는 Chrome에서 잘 작동하며 다른 브라우저와 "바인드"호환 가능하게 만드는 데 어려움이있을 수 있습니다.
인라인 처리기를 사용하면 호환되지 않는 콘텐츠 보안 정책에 너무 addEventListener
접근 방식은 이러한 관점에서 더 안전합니다. 물론 인라인 핸들러를 사용할 수는 unsafe-inline
있지만 이름에서 알 수 있듯이 CSP가 방지하는 JavaScript 익스플로잇을 모두 다시 가져 오기 때문에 안전하지 않습니다.
리스너를 프로토 타이핑하여 확장 할 수도 있고 (익명 함수가 아닌 참조가있는 경우) 'onclick'함수 라이브러리에 대한 호출 (다른 함수를 호출하는 함수)을 호출 할 수도 있습니다.
처럼
elm.onclick = myFunctionList
function myFunctionList(){
myFunc1();
myFunc2();
}
즉, onclick 호출을 막을 필요가 없으므로 myFunctionList () 함수를 변경하여 원하는 작업을 수행 할 수 있지만 버블 링 / 캐칭 단계를 제어하지 않아도되므로 최신 브라우저에서는 피해야합니다.
누군가가 나중에이 스레드를 찾은 경우를 대비하여 ...
element.onclick = function () {/ * 작업 수행 * /}
element.addEventListener ( 'click', function () {/ * do stuff * /}, false);
클릭 이벤트를 수신하고 콜백 함수를 실행합니다. 그럼에도 불구하고 그것들은 동등하지 않습니다. 둘 중 하나를 선택해야하는 경우 어느 것이 가장 적합한 지 파악하는 데 도움이 될 수 있습니다.
주요 차이점은 onclick은 단지 속성 이며 모든 객체 속성과 마찬가지로 두 번 이상 쓰면 덮어 씁니다 . 로 하여 addEventListener () 대신에, 우리가 할 수 단순히 이벤트 핸들러 바인딩 요소에, 우리는 우리가 어떤 덮어 속성의 걱정하지 않고 필요할 때마다 호출 할 수 있습니다. 여기 예가 나와 있습니다.
사용해보십시오 : https://jsfiddle.net/fjets5z4/5/
처음에는 onclick을 짧게 사용하고 더 단순 해 보이기 때문에 계속 사용하고 싶었습니다. 그러나 더 이상 사용하지 않는 것이 좋습니다. 인라인 JavaScript를 사용하는 것과 같습니다. 인라인 JavaScript와 같은 것을 사용하는 것은 현재 권장하지 않습니다 (인라인 CSS도 권장되지 않지만 다른 주제입니다).
그러나 addEventListener () 함수는 표준 임에도 불구하고 이전 브라우저 (버전 9 이하의 Internet Explorer)에서는 작동하지 않으며 이는 또 다른 큰 차이점입니다. 이러한 고대 브라우저를 지원해야하는 경우에는 onclick 방식을 따라야합니다. 그러나 jQuery (또는 그 대안 중 하나)를 사용할 수도 있습니다. 기본적으로 작업을 단순화하고 브라우저 간의 차이를 줄이므로 많은 시간을 절약 할 수 있습니다.
var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");
clickEvent.onclick = function(){
window.alert("1 is not called")
}
clickEvent.onclick = function(){
window.alert("2 is not called")
}
EventListener.addEventListener("click",function(){
window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
window.alert("2 is also called")
})
'this'
JavasSript에서 키워드가 참조하는 컨텍스트 가 다릅니다.
다음 코드를보십시오 :
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<input id="btnSubmit" type="button" value="Submit" />
<script>
function disable() {
this.disabled = true;
}
var btnSubmit = document.getElementById('btnSubmit');
btnSubmit.onclick = disable();
//btnSubmit.addEventListener('click', disable, false);
</script>
</body>
</html>
그것이하는 일은 정말 간단합니다. 버튼을 클릭하면 버튼이 자동으로 비활성화됩니다.
먼저 이러한 방식으로 이벤트를 연결하려고 button.onclick = function(),
하면 버튼을 클릭하여 onclick 이벤트가 트리거되지만 button.onclick 및 onclick 이벤트 핸들러 사이에 명시적인 바인딩이 없기 때문에 버튼이 비활성화되지 않습니다. 디버그하면 'this'
객체를 볼 수 있으며 객체를 참조하는 것을 볼 수 있습니다 'window'
.
두 번째로, btnSubmit.onclick = disable();
주석 을 달고 주석 을 해제
//btnSubmit.addEventListener('click', disable, false);
하면 button.onclick 이벤트와 onclick 이벤트 핸들러 사이에 명시 적 바인딩이 있기 때문에 버튼이 비활성화되어 있음을 알 수 있습니다. 당신은 디스 에이블 기능으로 디버깅하면 볼 수 있습니다 당신은 'this'
받는 사람을 의미 button control
오히려보다 window
.
불일치하는 JavaScript에 대해 내가 싫어하는 것입니다. Btw, jQuery ( $('#btnSubmit').on('click', disable);
)를 사용하는 경우 명시 적 바인딩을 사용합니다.
btnSubmit.onclick = disable;
(함수를 지정하지 말고 함수를 지정하십시오). 그런 다음 두 경우 모두 this
버튼 요소를 참조합니다.
onclick은 기본적으로 요소를 클릭 할 때 기능을 수행하는 addEventListener입니다. 따라서 계산기 버튼과 같은 간단한 작업을 수행하는 버튼이있을 때 유용합니다. addEventlistener는 DOM 또는 모든 컨텐츠가로드 될 때 작업을 수행하는 것과 같이 window.onload와 유사하지만 더 많은 제어를하는 등 여러 가지 작업에 사용될 수 있습니다.
참고로 실제로 인라인으로 두 개 이상의 이벤트를 사용하거나 적어도 각 함수를 세미콜론으로 분리하여 onclick을 사용하여 사용할 수 있습니다 ....
나중에 문제가 발생할 수 있으며 지저분한 imo 일 수 있으므로 인라인으로 함수를 작성하지 않습니다. 스크립트 파일에서 이미 수행 된 함수를 호출하는 데 사용하십시오.
당신이 사용하는 것은 당신이 원하는 것에 달려 있다고 생각합니다. 복잡한 조작을위한 addEventListener 및 단순을위한 onclick. 일부 프로젝트는 요소에 특정 프로젝트를 첨부하지 않고 탭이 버튼에 있는지 여부를 결정하고 눌린 내용에 따라 특정 작업을 수행하는보다 글로벌 이벤트 리스너를 구현하는 것을 보았습니다. 잠재적으로 내가 생각하는 문제로 이어질 수있는 이모, 비록 이벤트 리스너가 클릭 할 때마다 처리해야한다면 리소스 낭비는 적지 만
function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }