Sometimes I see functions with parameter like this:
$('#my_div').bind("mouseover mouseenter", function (e) {
console.log(e);
var el = $("#" + e.type);
var n = el.text();
el.text(++n);
});
I don't get what is being passed into the function. I would understand it if it is something like (function(e){ .... }(parameter); but it is not. Can someone shade some light
jQuery will actually call that function, since functions are first class citizen objects in JavaScript, so it can be passed as an argument. e is for event args which jQuery will provide.
This pattern is called "callback".
There's always a parameter being passed, it's just that you're not the one passing it directly. The browser is.
In this case, you're talking about the event handlers. Basically what happens is that when the event is triggered, the browser will pass an event object to the callback of the event listener (the callback you provided).
If you want to know what's inside the event object, look into this mozilla docs page https://developer.mozilla.org/en-US/docs/Web/API/Event
If you want to know how browsers handle the whole passing of event object, here's the specification: http://www.w3.org/html/wg/drafts/html/master/webappapis.html#the-event-handler-processing-algorithm look under 4) where it says "process the event E as follows"
The function isn't actually being called yet. This is telling the browser to call that function for you when the 'mouseover' or 'mouseenter' event happens. In this case, when the browser does that it will pass an event object which will get bound to the local variable e in side of the function.
Related
I have seen this kind of code in one of Google's google maps documentation. My question is about the listener. Instead of the callback function passed immediately after the 'click' action the showArrays() function is called but not passed nothing as parameter. On the other hand showArrays() function uses event as parameter. Please explain me this kind of calling the function.
element.addListener('click', showArrays);
//some code here
}
function showArrays(event) {
// some code here
}
Think of the names of functions as variables themselves. showArrays is a variable, that, when given an event, does something with it.
You can pass the functions name as a parameter to addListener so that it can call the callback when the element is clicked on. It's important to note that you are not calling the function in the first line, only passing a reference to that function.
You can show this property in the browser's console with this test:
function test() { console.log("Test was called"); }
Notice if you say var x = test nothing is printed to the console. But if you say var x = test() you see the print. Finally, if you do var x = test; x() you will see the print out, because you called the test function after assigning it a new name.
Notice that in the element.addListener('click', showArrays) line, showArrays does NOT have brackets after it. That means it's not being called. Instead, the entire function is being passed as a parameter to the addListener method.
Event listeners in JS will take the handler function you provide when you attach them with addListener (or addEventListener, more commonly), and, when the event occurs, they will call that function and pass an event object to it.
In other words, showArrays is not being called until the element is clicked, and all event listeners inherently get passed an event object at that point, detailing the specific properties of the event.
One of the syntax cases for describing a function is:
var showArrays = function (event) {
// of the code here
}
and it is precisely this argument value that the addEventListener method uses, and even other functions such as setTimeout or setInterval, among others.
addEventListener method always sends the "event" object as an argument to the callback function. When you use the anonymous function, it is obvious to see it:
element.addEventListener('click', function(event) {
// some code here
});
But when you send to the addEventListener method a link to the function you want to be called when the event occures (in your case it is a link to showArrays function), addEventListener sends "event" object as an argument to this function just on itself. So, although it's not obvious to see it, but the "event" object is being sent to showArrays function automatically.
element.addEventListener('click', showArrays); // the event object will be sent automatically
And you will have an access to the "event" object inside the showArrays function. But, of corse, in showArrays function declaration you should have a parameter for catching the "event" object.
function showArrays() {} // it's not going to work
function showArrays(event) {} // it will work
I am trying to pass function reference as event handler in jQuery. I would like to use a shorthand like in the simple example below...
$("a").click(console.debug.bind(undefined,this));
...rather than passing explicitly the whole function body:
$("a").click(function() {
console.debug(this)
});
Moreover, I would like to access elements selected by jQuery in my shorthand function (and pass them as a parameter). In other words: I expect to have a result of $("a") as a this (or any other code that will retrieve the result).
So far I've tried:
var a = function() {
console.debug(this);
};
var b = console.debug.bind(undefined,this);
$("a").click(function() {console.debug(this)}); // prints link
$("a").click(a); // prints link
b(); // prints Window
$("a").click(console.debug.bind(undefined,this)); // prints Window & jQuery.Event
Here is the fiddle:
https://jsfiddle.net/hbqw2z93/1/
My questions are:
Is it possible to use such construction and meet all requirements, without definition of additional variables - just one line as shown above?
Is it possible to access jQuery's selection result using described approach?
Why in the given scope this becomes 'merged' Window and jQuery.Event object?
You already using it, aren't you? :) It's limited, but it works in your own fiddle
jQuery will pass event object to your specified function. You can use function bind to pass that as an argument (you already have this working in your fiddle)
It doesn't. See what's happening:
jQuery passed one argument to click handler function - event object. You pass console.debug.bind(undefined, this) as a handler function so jQuery will call it with one argument.
Then, when you are binding you are asking to use 'undefined' as a 'this' object inside the function and sending an extra argument - 'this', which is a Window at this scope because you are binding at the highest level.
So when actual click happens, jQuery calls console.debug with two parameters - Window object that was bound during click() and jQuery event that is always passed to click handler. console.debug() can accept and display multiple objects, which is exactly what you see in the developer console.
The first parameter of bind is the new context to use for this. By passing undefined you are essentially not passing the first parameter.
The second and further parameters are passed into the function as the first values.
Note also that this when in the global scope, refers to the window object.
So here, b...
console.debug.bind(undefined,this);
is identical to...
function(){ console.debug(window); }
..since you're passing this (which is window) as the first parameter to debug.
By default, when you attach an event to the element, this will automatically point to the element which caught the event, so bind shouldn't even be necessary, which is why $("a").click(a); worked without using bind.
When I started learning javascript I thought that the browser would simply run the javascript in onclick attribute of elements as if it was inside a script tag. However I realize that is not the case because you can use certain parameters inside these attributes. For example onclick="foo(this, event)" passes the event triggered and the element that the event was triggered on to function foo.
I wonder what other parameters can be used inside these tags? The documentation on w3schools does not mention anything about this. I would also like to know how these attributes are implemented; how is the function called and in what scope (I know that foo will be called like element.foo() but this is not true for other javascript expressions). Is there a comprehensive documentation anywhere? my best guess at the moment is that the implementation looks like this:
element.onclickfunction = function(){
var event = new Event(...)
eval(element.onclick)
}
Edit:
none of the responses really answered my question. I was interested to know what other special parameters can be passed to the function specified in an event handler and how the parameter this is interpreted to be the Element. I am picking the best answer because he provided a link to mdn where EventHandler interface is described.
In JavaScript, you can register an event listener on any DOM element, the document itself, the context window, or any other objects that support events. There are a whole bunch of events that are defined in a whole bunch of web standards. A good resource that lists these out is the Mozilla Developer Network.
The EventListener that gets registered to the event only takes one parameter: the event. You can see that it only has one method, handleEvent, which takes only one parameter.
To pass other stuff into the event handler, you can take advantage of closures or bind(). I'm going to borrow from this answer to demonstrate how bind() works:
elem.addEventListener(function(a1, a2, e) {
// inside the event handler, you have access to both your arguments
// and the event object that the event handler passes
}.bind(elem, arg1, arg2));
Binding elem, arg1, and arg2 to the function means that the this of the function becomes elem, and the first two arguments of the function become arg1 and arg2. The e argument is still the event that triggered the function, just like always. Binding stuff like this is super useful when you want to pass stuff from outside the event handler to inside the handler. You can read more about bind() here.
With regards to your specific question about onclick(), the principle is basically the same except your registering a specific click event handler to an element. It too only takes one argument, and that is the MouseEvent object. But like with any function, you can still bind other arguments to it. See here for more info.
function(e){
if(e.which==='37'){
//
}
}
After I search for how does this e or event parameter work on the internet for while, I still did not find an answer..
Assume e has not been defined before this function call... what will e become after this function call? an Object?
Does the which cause it to become a object?
can we pass a undefined variable into a function in javascript? what are expected to happen if I did so?
The variable e is a parameter of the function. Forget about events for a minute and consider this function:
function doStuff(e) {
alert(e.which);
}
This function accepts something called e and alerts the which property of that value. Note that this function is the same as:
function doStuff(firstParam) {
alert(firstParam.which);
}
This shows that we can call the parameter anything we like, but we've chosen to call it e.
You could invoke the function directly like:
doStuff({ which: 46 });
doStuff({ which: 57 });
doStuff({ which: "Bob" });
Each of these invokes doStuff and passes in some object with a which property, which the doStuff function body refers to as e.
Now suppose we use doStuff as an event listener:
document.addEventListener("keypress", doStuff);
This tells the browser to invoke doStuff every time the user presses a key. What gets used as the e value depends on which key caused the keypress event to occur.
what will e become after this function call?
e does not exist outside of this function. JavaScript scope is function-based, and e is limited in scope to this function, since it is a formal parameter of the function.
Does the which cause it to become a object?
No, the which is simply an object property of the Event object that is supplied as the e parameter. When a function is invoked as an event listener, the value passed as the function 's first parameter is always an object (specifically, an Event object, with details about the event).
Assume e has not been defined before this function call... what will e become after this function call?
Nothing. It will remain undefined.
Normally, you would use a function like this as an event handler. In that case, the event object (the use of which implies a keyboard event if you want to be specific) is created by the code that calls the function.
For the most part, that code will be built into the browser and not written by you directly.
Often I see javascript code where event handlers (like onmousemove) are assigned dynamically.
Example:
document.getElementById('foo').onmousemove = function(e)
{ /* do some stuff with event e */ }
Apparently this 'e' parameter is some kind of event object. Where does that come from, as in: who or what defines what this 'e' parameter is when the function is called, and can I also do this in static html?
I mean like this:
<div id='foo' onmousemove='Bla(e)'> ... </div>
What should I fill in for 'e' to get that same event thing? And can I also combine that with more parameters, like
<div id='foo' onmousemove='Bla(this,e,4)'> ... </div>
where e is, again, supposed to be the event object?
Event handlers are defined as callback methods. A callback is (hence the expression) called from another process at a later time. This is done by the environment (the browser in this case) at the time an event fires.
it calls your callback function and passes in the event object.
The event object is stored in window.event inside of any event handler, so you do not need to worry about your handler conforming to accepting it as a parameter.
In your second and third examples, the e parameter will be passed as undefined because no variable e exists in that scope (unless you have a global e).
This is what's known as a callback method. The event is initially created by the operating system, sent to the web browser, which then passes it off to you in javascript Event object.
I'm not sure, but I think the event is an object instance of ActionEvent. I don't think ActionEvent can be manually instantiated, so you can't do it in static HTML. Even if it would be possible, it certainly wouldn't be best practice.