jQuery.click() vs onClick
Asked Answered
H

18

621

I have a huge jQuery application, and I'm using the below two methods for click events.

First method

HTML

<div id="myDiv">Some Content</div>

jQuery

$('#myDiv').click(function(){
    //Some code
});

Second method

HTML

<div id="myDiv" onClick="divFunction()">Some Content</div>

JavaScript function call

function divFunction(){
    //Some code
}

I use either the first or second method in my application. Which one is better? Better for performance? And standard?

Harmonicon answered 27/9, 2012 at 18:2 Comment(2)
You can learn about the various ways to attach event handlers and their advantages/disadvantages here: quirksmode.org/js/introevents.html. jQuery is just a nice wrapper for advanced event registration.Hadhramaut
Remember to put the click function inside the $(document).ready(function().Bailable
T
618

Using $('#myDiv').click(function(){ is better as it follows standard event registration model. (jQuery internally uses addEventListener and attachEvent).

Basically registering an event in modern way is the unobtrusive way of handling events. Also to register more than one event listener for the target you can call addEventListener() for the same target.

var myEl = document.getElementById('myelement');

myEl.addEventListener('click', function() {
    alert('Hello world');
}, false);

myEl.addEventListener('click', function() {
    alert('Hello world again!!!');
}, false);

http://jsfiddle.net/aj55x/1/

Why use addEventListener? (From MDN)

addEventListener is the way to register an event listener as specified in W3C DOM. Its benefits are as follows:

  • It allows adding more than a single handler for an event. This is particularly useful for DHTML libraries or Mozilla extensions that need to work well even if other libraries/extensions are used.
  • It gives you finer-grained control of the phase when the listener gets activated (capturing vs. bubbling)
  • It works on any DOM element, not just HTML elements.

More about Modern event registration -> http://www.quirksmode.org/js/events_advanced.html

Other methods such as setting the HTML attributes, example:

<button onclick="alert('Hello world!')">

Or DOM element properties, example:

myEl.onclick = function(event){alert('Hello world');}; 

are old and they can be over written easily.

HTML attribute should be avoided as It makes the markup bigger and less readable. Concerns of content/structure and behavior are not well-separated, making a bug harder to find.

The problem with the DOM element properties method is that only one event handler can be bound to an element per event.

More about Traditional event handling -> http://www.quirksmode.org/js/events_tradmod.html

MDN Reference: https://developer.mozilla.org/en-US/docs/DOM/event

Tricyclic answered 27/9, 2012 at 18:4 Comment(17)
Lets say you run the $('#myDiv').click(function(){ code first, then you generate 20 rows of HTML dynamically from JavaScript and each row has a button on it that when clicked the JavaScript is required to execute that same function. If you do that first then it won't work as the event handler has been added before the HTML has been generated. It would seem easier to just throw in the onclick="functionName()" into the dynamically generated HTML then the button works straight away. Or do you know of a more elegant solution for this situation?Pharynx
@Pharynx for that case jQuery offers .delegate() function. It will attach event to any element that will appear in the future on the site.Dignity
@Dignity Thanks that function sounds great, I'll be using that in future!Pharynx
@Pharynx the jQuery .live() function might be an simpler solution for what you are after http://api.jquery.com/live/. A good article on the differences between .bind(), .live() and .delegate() hereUnsubstantial
@SimonRobb .live is deprecated. Use .delegate for older versions or use .on for newer jQuery versions.Tricyclic
@Vega, Good points. What about readability? Now you have to search all referenced JS files on the page to see all click handlers of an element by element's ID instead of searching for the function name. What's your take on this?Diminution
I agree with @supertonsky. I STRONGLY disagree that $('#myDiv').click(function(){ is better. In a large javascript application binding with an event becomes massively difficult to find all the references binding to that target. Is it the binding on a class, an id, a child references to a html tag? And what happens if css changes and class names you bound to need to be changed? In my experience working with others code it becomes very ugly very fast.Goa
@Goa Your disagreement is based on bad coding practices. If the code is ugly, you should consider refactoring it.. but not disagree on a better approach just because it is hard to find reference in a ugly code. Also, It is easy to find the reference if you follow a simple rule to bind the handler only by an ID or class. Any other way such as binding using traversal methods is bad coding and you cannot blame the standard if it is poor code.Tricyclic
@Diminution I believe searching by ID or class or by function name in js files is same. However it is very hard when you bind a handler using a traversal method like $('#myTable').find('tr').click( or $('.someclass').parent().click( - but those are bad coding styles.Tricyclic
@Goa Having multiple elements with the same ID is bad coding in general, and may have erratic behavior. Instead, for multiple items with a listener it is proper to do jQuery('#container').on('click','.listitem', function(){...}) or in plain javascript, set document.getElementById('container').addEventListener(... and check event.target.getAttribute('class') in the listener.Amputate
@Diminution At least we now have the ability to use the HTML panel's Events tab in Firebug. I know it's not exactly what you're after but nonetheless, it remains a great aid which allows you to inspect the actual event listeners registered for a selected DOM node at any given time, as opposed to scanning the code base and looking at ones that might be registered at some point.Infrangible
I have a trouble use this code without run it inside of ready jquery function: $(document).ready(function() { ... });Kamin
Although the answer is very good, nobody seems to question the purpose of onClick events, no matter the way of calling it. The purpose is to trigger an action without refreshing the page, but in 99% of the cases we need to pass one or more parameters. In that case, it really doesn't matter if you use data-param="value" or onClick="function(param)", either way they are visible and can be overwritten. I'm using onClick, but I always check and sanitise everything before processing the data, so it doesn't matter to me fi the parameters are visible.Kerikeriann
"HTML attribute should be avoided as It makes the markup bigger" oh yeah, but now I have to give id to all my elelements. Also, LOVE answers that say "should be avoided because its wrong"Allopath
"HTML attribute should be avoided as It makes the markup bigger" having this in mind will lead to spaghetti code, HTML attribute event is 100% valid. I don't mind if ID used in getting element to bind the event. but i've seen so many "senior" developer using long query with class only. The result? other developer will have a hard time searching where the functionality of the event. I believe the best practice is using anything where other developer can find the function easily, people on vue.js has written about this vuejs.org/v2/guide/events.html#Why-Listeners-in-HTMLThud
This is general comment. Some comments are saying live is deprecated, use delegate or on instead etc. But some of us, are still using live and delegate. They don't want to upgrade. This is sad.Truckle
IMHO - I prefer seeing the onclick in the tag as that clearly shows there is an onclick handler and what it is. Adding an event listener later in the file requires the reader to search ALL of the code for any such listeners, including any included files that might have handlers for classes, e.g.Sharkskin
W
68

For better performance, use the native JavaScript. For faster development, use jQuery. Check the comparison in performance at jQuery vs Native Element Performance.

I've done a test in Firefox 16.0 32-bit on Windows Server 2008 R2 / 7 64-bit

$('span'); // 6,604 operations per second
document.getElementsByTagName('span'); // 10,331,708 operations/sec

For click events, check Native Browser events vs jquery trigger or jQuery vs Native Click Event Binding.

Testing in Chrome 22.0.1229.79 32-bit on Windows Server 2008 R2 / 7 64-bit

$('#jquery a').click(window.testClickListener); // 2,957 operations/second

[].forEach.call( document.querySelectorAll('#native a'), function(el) {
    el.addEventListener('click', window.testClickListener, false);
}); // 18,196 operations/second
Wharve answered 27/9, 2012 at 18:9 Comment(2)
jQuery should be able to run in many different environments which makes it more robuts and it's easier to write, maintain but if speed is the most important then jQuery is not the answerThelma
Be careful when using forEach cause is not all browser compatible, i think not for IE for example. Maybe a polyfill will be useful.Coonskin
T
43

From what I understand, your question is not really about whether to use jQuery or not. It's rather: Is it better to bind events inline in HTML or through event listeners?

Inline binding is deprecated. Moreover this way you can only bind one function to a certain event.

Therefore I recommend using event listeners. This way, you'll be able to bind many functions to a single event and to unbind them later if needed. Consider this pure JavaScript code:

querySelector('#myDiv').addEventListener('click', function () {
    // Some code...
});

This works in most modern browsers.

However, if you already include jQuery in your project — just use jQuery: .on or .click function.

Themistocles answered 27/9, 2012 at 18:2 Comment(7)
It is possible to register multiple functions using inline HTML like <div onclick="handler1();handler2();handler3();"></div>Downstate
This way you're still registering only one "expression". For example, if handler1 throws an error, handler2 and handler3 won't ever get called. Moreover, you're unable to dynamically add and remove certain fuctions from the listener. And last but not least, handler1, handler2 and handler3 have to be declared in the global scope which is a smell.Sandpiper
Using try..catch inside the functions won't work when handler2 in undefined. FYI inline JavaScript obviously doesn't work when JS is disabled in user's browser, please do not misinform others.Sandpiper
I mentioned I was not sure about disabled JavaScript. I am not misinforming or deceiving othersDownstate
In that case you can try the following <div onclick="function() { try { handler1();handler2();handler3(); } catch { } }"></div>Downstate
Oh, wow, it's both more readable and certainly more convenient than addEventListener. Keep up with the good code!Sandpiper
Pointing out a problem in the post: "Inline binding is deprecated." Are you sure about that? (HTML spec §8.1.7.1 disagrees html.spec.whatwg.org/multipage/…) My impression: everyone echoes to each other it's a bad practice to use them, but few think critically about what memes they ingest. Some antibodies: event listeners are imperatively (not declaratively) linked (usually via some lookup, frequently aided by adding extraneous attributes), are invisible on the DOM, and can't be rewired by editing an attribute on a live HTML document.Hydrastis
C
23

Go for this as it will give you both standard and performance.

 $('#myDiv').click(function(){
      //Some code
 });

As the second method is simple JavaScript code and is faster than jQuery. But here performance will be approximately the same.

Chicory answered 28/9, 2012 at 6:51 Comment(0)
F
21

You could combine them, use jQuery to bind the function to the click

<div id="myDiv">Some Content</div>

$('#myDiv').click(divFunction);

function divFunction(){
 //some code
}
Fixing answered 27/9, 2012 at 18:4 Comment(0)
B
16

$('#myDiv').click is better, because it separates JavaScript code from HTML. One must try to keep the page behaviour and structure different. This helps a lot.

Brat answered 27/9, 2012 at 18:5 Comment(1)
This answer makes sense as people who design and write js stuff are different in most of the cases. And it feels strange to upvote this after almost 4 years since this was posted!!Halftone
S
13

Difference in works. If you use click(), you can add several functions, but if you use an attribute, only one function will be executed - the last one.

DEMO

HTML

<span id="JQueryClick">Click #JQuery</span> </br>
<span id="JQueryAttrClick">Click #Attr</span> </br>

JavaScript

$('#JQueryClick').click(function(){alert('1')})
$('#JQueryClick').click(function(){alert('2')})

$('#JQueryAttrClick').attr('onClick'," alert('1')" ) //This doesn't work
$('#JQueryAttrClick').attr('onClick'," alert('2')" )

If we are talking about performance, in any case directly using is always faster, but using of an attribute, you will be able to assign only one function.

Selene answered 27/9, 2012 at 18:32 Comment(1)
We can execute more than one functions using attribute like $('#JQueryAttrClick').attr('onClick'," alert('2');alert('3');alert('4')" )Downstate
A
11

IMHO, onclick is the preferred method over .click only when the following conditions are met:

  • there are many elements on the page
  • only one event to be registered for the click event
  • You're worried about mobile performance/battery life

I formed this opinion because of the fact that the JavaScript engines on mobile devices are 4 to 7 times slower than their desktop counterparts which were made in the same generation. I hate it when I visit a site on my mobile device and receive jittery scrolling because the jQuery is binding all of the events at the expense of my user experience and battery life. Another recent supporting factor, although this should only be a concern with government agencies ;) , we had IE7 pop-up with a message box stating that JavaScript process is taking to long...wait or cancel process. This happened every time there were a lot of elements to bind to via jQuery.

Amish answered 19/3, 2013 at 19:25 Comment(0)
H
10

Seperation of concerns is key here, and so the event binding is the generally accepted method. This is basically what a lot of the existing answers have said.

However don't throw away the idea of declarative markup too quickly. It has it's place, and with frameworks like Angularjs, is the centerpiece.

There needs to be an understanding that the whole <div id="myDiv" onClick="divFunction()">Some Content</div> was shamed so heavily because it was abused by some developers. So it reached the point of sacrilegious proportions, much like tables. Some developers actually avoid tables for tabular data. It's the perfect example of people acting without understanding.

Although I like the idea of keeping my behaviour seperate from my views. I see no issue with the markup declaring what it does (not how it does it, that's behaviour). It might be in the form of an actual onClick attribute, or a custom attribute, much like bootstraps javascript components.

This way, by glancing just at the markup, you can see what is does, instead of trying to reverse lookup javascript event binders.

So, as a third alternative to the above, using data attributes to declarativly announce the behaviour within the markup. Behaviour is kept out of the view, but at a glance you can see what is happening.

Bootstrap example:

<button type="button" class="btn btn-lg btn-danger" data-toggle="popover" title="Popover title" data-content="And here's some amazing content. It's very engaging. Right?">Click to toggle popover</button>

Source: http://getbootstrap.com/javascript/#popovers

Note The main disadvantage with the second example is the pollution of global namespace. This can be circumvented by either using the third alternative above, or frameworks like Angular and their ng-click attributes with automatically scope.

Horodko answered 18/10, 2014 at 12:16 Comment(1)
+1! :D Other benefits of the declarative form: because of the event handler attribute's visibility on the DOM node (unavailable with addEventListener), one can (as I have) create an attribute editor that edits a given element's attribute value, powerfully rewiring what an element does on a live HTML document.Hydrastis
B
5
<whatever onclick="doStuff();" onmouseover="in()" onmouseout="out()" />

onclick, onmouseover, onmouseout, etc. events are actually bad for performance (in Internet Explorer mainly, go figure). If you code using Visual Studio, when you run a page with these, every single one of these will create a separate SCRIPT block taking up memory, and thus slowing down performance.

Not to mention you should have a separation of concerns: JavaScript and layouts should be separated!

It is always better to create evenHandlers for any of these events, one event can capture hundreds/thousands of items, instead of creating thousands of separate script blocks for each one!

(Also, everything everyone else is saying.)

Brendanbrenden answered 27/9, 2012 at 18:18 Comment(3)
What about angular, vue,... - they break concept of separation - and it not induce any problems in applications writen using this frameworks (in fact it speed up proces of creating software) - ?Selsyn
@KamilKiełczewski Definitely since 2012 a lot has changed! This used to be a major SOC issue back then but now a days we do it everywhere. The only difference I suppose is that we're letting some framework compile our code and take (click) or whatever events and turn them into something different. But it's the same idea in the end right :D Crazy how things come back full circle!Brendanbrenden
I agree with you and I wrote down my thoughts hereSelsyn
L
5

Performance

There are already many good answers here however, authors sometimes mention about performance but actually nobody investigate it yet - so I will focus on this aspect here. Today I perform test on Chrome 83.0, Safari 13.1 and Firefox 77.0 for solutions mention in question and additionally few alternative solutions (some of them was mention in other answers).

Results

I compare here solutions A-H because they operate on elements id. I also show results for solutions which use class (I,J,K) as reference.

  • solution based on html-inline handler binding (B) is fast and fastest for Chrome and fastest for small number of elements
  • solutions based on getElementById (C,D) are fast, and for big number of elements fastest on Safari and Firefox
  • referenced solutions I,J based are fastest for big num of elements so It is worth to consider use class instead id approach in this case
  • solution based on jQuery.click (A) is slowest

enter image description here

Details

Actually It was not easy to design performance test for this question. I notice that for all tested solutions, performance of triggering events for 10K div-s was fast and manually I was not able to detect any differences between them (you can run below snippet to check it yourself). So I focus on measure execution time of generate html and bind event handlers for two cases

  • 10 divs - you can run test HERE
  • 1000 divs - you can run test HERE

// https://mcmap.net/q/64062/-jquery-click-vs-onclick
let a= [...Array(10000)];

function clean() { test.innerHTML = ''; console.clear() }

function divFunction(el) {
  console.log(`clicked on: ${el.id}`);
}

function initA() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> $(`#myDiv${i}`).click(e=> divFunction(e.target)));
}

function initB() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box" onclick="divFunction(this)">${i}</div>`).join``;
}

function initC() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.getElementById(`myDiv${i}`).onclick = e=> divFunction(e.target) );
}

function initD() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.getElementById(`myDiv${i}`).addEventListener('click', e=> divFunction(e.target) ));
}

function initE() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.querySelector(`#myDiv${i}`).onclick = e=> divFunction(e.target) );
}

function initF() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> document.querySelector(`#myDiv${i}`).addEventListener('click', e=> divFunction(e.target) ));
}

function initG() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> window[`myDiv${i}`].onclick = e=> divFunction(e.target) );
}

function initH() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  a.map((x,i)=> window[`myDiv${i}`].addEventListener('click',e=> divFunction(e.target)));
}

function initI() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  [...document.querySelectorAll(`.box`)].map(el => el.onclick = e=> divFunction(e.target));
}

function initJ() {
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  [...document.querySelectorAll(`.box`)].map(el => el.addEventListener('click', e=> divFunction(e.target)));
}

function initK() {  
  test.innerHTML = a.map((x,i)=> `<div id="myDiv${i}" class="box">${i}</div>`).join``;
  $(`.box`).click(e=> divFunction(e.target));
}



function measure(f) {  
  console.time("measure "+f.name);
  f();
  console.timeEnd("measure "+f.name)
}
#test {
  display: flex;
  flex-wrap: wrap;
}

.box {
  margin: 1px;
  height: 10px;
  background: red;
  font-size: 10px;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>This snippet only presents used solutions. Click to solution button and then click on any red box to trigger its handler</div>
<button onclick="measure(initA)">A</button>
<button onclick="measure(initB)">B</button>
<button onclick="measure(initC)">C</button>
<button onclick="measure(initD)">D</button>
<button onclick="measure(initE)">E</button>
<button onclick="measure(initF)">F</button>
<button onclick="measure(initG)">G</button>
<button onclick="measure(initH)">H</button>
<button onclick="measure(initI)">I</button>
<button onclick="measure(initJ)">J</button>
<button onclick="measure(initK)">K</button>
<button onclick="clean()">Clean</button>

<div id="test"></div>

Here is example test for Chrome

enter image description here

Lacquer answered 26/6, 2020 at 8:31 Comment(0)
M
4

Neither one is better in that they may be used for different purposes. onClick (should actually be onclick) performs very slightly better, but I highly doubt you will notice a difference there.

It is worth noting that they do different things: .click can be bound to any jQuery collection whereas onclick has to be used inline on the elements you want it to be bound to. You can also bind only one event to using onclick, whereas .click lets you continue to bind events.

In my opinion, I would be consistent about it and just use .click everywhere and keep all of my JavaScript code together and separated from the HTML.

Don't use onclick. There isn't any reason to use it unless you know what you're doing, and you probably don't.

Marietta answered 27/9, 2012 at 18:5 Comment(4)
Even if "better" isn't explicitly defined, it's almost never a good idea to put event handlers into your markup directlyHyperaesthesia
@Jayraj when did I ever say in my answer that was a good idea?Marietta
By saying .click wasn't better than onclick ("Neither one is better") it was implied that onclick is almost, or just as good a way to write code, when in fact .click is the better practice by a mile. Sorry, but IMHO you should rephrase your answerHyperaesthesia
@ExplosionPills I would remove the part of the answer that says neither is better. The paragraph at the end sounds like a contradiction.Natality
N
4

Onclick Function Jquery

$('#selector').click(function(){ //Your Functionality });

Nebuchadnezzar answered 11/6, 2019 at 8:18 Comment(0)
G
3

Most of the time, native JavaScript methods are a better choice over jQuery when performance is the only criteria, but jQuery makes use of JavaScript and makes the development easy. You can use jQuery as it does not degrade performance too much. In your specific case, the difference of performance is ignorable.

Goingson answered 27/9, 2012 at 18:5 Comment(0)
O
3

Well, one of the main ideas behind jQuery is to separate JavaScript from the nasty HTML code. The first method is the way to go.

Opsis answered 27/9, 2012 at 18:6 Comment(0)
H
2

The first method is to prefer. It uses the advanced event registration model[s], which means you can attach multiple handlers to the same element. You can easily access the event object, and the handler can live in any function's scope. Also, it is dynamic, i.e it can be invoked at any time and is especially well-suited for dynamically generated elements. Whether you use jQuery, an other library or the native methods directly does not really matter.

The second method, using inline attributes, needs a lot of global functions (which leads to namespace pollution) and mixes the content/structure (HTML) with the behavior (JavaScript). Do not use that.

Your question about performance or standards can't be easily answered. The two methods are just completely different, and do different things. The first one is mightier, while the second one is despised (considered bad style).

Hyperostosis answered 27/9, 2012 at 18:5 Comment(0)
T
2

The first method of using onclick is not jQuery but simply Javascript, so you do not get the overhead of jQuery. The jQuery way can expanded via selectors if you needed to add it to other elements without adding the event handler to each element, but as you have it now it is just a question if you need to use jQuery or not.

Personally since you are using jQuery I would stick with it as it is consistent and does decouple the markup from the script.

Tramel answered 27/9, 2012 at 18:5 Comment(1)
The jQuery example is practically the same thing as document.querySelector('#something').addEventListener(... or similar in plain Javascript, so that isn't the point. Similarly you can catch bubbling events from child nodes in Javascript, not just with jQuery shortcuts. The heart of the matter is these events should be in the controller (javascript behavior definitions file) rather than the view (scattered here and there in the html, requiring global-variable-functions or worse yet, inline code.)Amputate
R
1

Say you have a button nested inside a Javascript/Jquery generated html element (the .html() or .innerHTML kind of elements) then you need to first pick outtermost element(parent) and do this

var parentElement = $('#outermostElement')
 parentElement.click('button', function(){
    console.log('clicked')
}) 

by outermost element I mean the element that embeds the .html() e.g

outermostElement.html("<div><button>click<button><div>")
Ruler answered 10/12, 2021 at 22:7 Comment(1)
Can you please edit in an explanation of this answer? There are several well-explained answers here already.Arman

© 2022 - 2024 — McMap. All rights reserved.