Note that "setter" is meant in the broader sense, i.e. any method that does set or change a certain property. Likewise "change event" is meant in the broader sense, i.e. an event that indicates that a certain property has changed.
I'm struggling to understand if there is a certain logic, according to which in Javascript events are sometimes fired when a setter is called programmatically and sometimes not.
Examples of setters that don't fire a corresponding change event (for them those events are only fired with user-interaction):
<input>-tags,<select>-tags and<textarea>-tags:
programmatically settingtag.value = newValuedoes not fire a 'change'-eventhistory.pushState()changeshistory.statebut the corresponding 'popstate'-event is not fired
Examples of setters that do fire a corresponding change Event:
- 'hashchange' is fired even when set programatically with
document.location.hash='#x=y' - 'resize' is fired even when the window size of a popup window is set programmatically via
win.resizeTo(x, y) <video>and<audio>-tags:video.currentTime = newValue;does fire a 'timeupdate'-Eventvideo.pause()(as a setter for propertyvideo.paused) does fire a 'paused'-event.
(I've tested these with Firefox 104)
I understand the logic of not firing an event (i.e. the first group) as follows:
If we set a property ourselves programmatically, then we know that it has changed, so there is no need for an event. There are situations where it can be practical, but it is not necessary. It could even cause harm. Imagine, we have two <input> fields with a different stepattribute (e.g of type ruler) synchronized by listening to each other's change event. When the first changes by user interaction and fires a
change event, we adapt the second with its setter. If that setter would fire a change event again, the first would listen to it. With different steps this can lead to an infinite ping-pong.
According to this reasoning, the rule should be that an event should be fired only when there is some input from the exterior world.
(Maybe in functional programming language one could pin it down to an I/O Monad)
For the second group I recognize that there are some setters that might not be successful or at least not immediately. E.g. window.resizeTo() succeds only, if the window was opened by us.
Also the setter for video.currentTime might not be successful, e.g. if the video is not yet loaded. So in these cases an event could seem necessary, to tell us if and when the setting succeeded.
But the setting of document.location.hash seems immediate to me (no Http-Request needed), so why an Event here?
And also for video.pause() I don't understand the event, as it (in contrast to video.play()) does not return a Promise and is supposed to be immediate and always successful.
The information which setters induce change-events and which don't is not easily available (at least I didn't find e.g. the information about the fact that setters for input fields don't induce a change event on Mozilla, but was testing myself). Therefore I'm looking for a rule of thumb. So I'm curious to hear if there is more to it than the two reasonings I've sketched above. This would also be useful when creating own objects (e.g. custom-html elements) and having to decide, whether to throw an event in a setter or not.
Remark 1: As a reaction to comments, I would like to stress that I am of course aware that one can find the information for each event somewhere in the specs or on MDN. Just sometimes not as prominently as I would have expected. It was not my main concern to get this information in a particular case, but I was more looking for the logic behind the different behavior, in order to get a rule of thumb or alternatively an overview if it already existed. Nevertheless some provided links and comments were already very helpful and I'm going to write an own answer, which I would be happy to turn into a community wiki, if there is interest to turn it into such an overview.
Remark 2: My original title was asking for "native Javascript". My intention was to not ask about arbitrary libraries like Jquery, but to restrict to officially specified Javascript APIs. However, I was informed in the comments that "native" is not the proper word, in particular as all my examples apparently were about the DOM API while native Javascript has nothing like a DOM.