I looked at the above piece of code and tried my best to search for solutions and posted it here after giving it my all. This is my current understanding of the code:
debounce() is called when there is an input and onInput() is passed to it as a callback, and debounce function return another function , the function being returned takes an argument which is the function passed by the debounce() a.k.a the onInput() , I am stuck # func.apply(null , args);
1.Isn't func and args the same thing ????
Someone please explain step by step is possible..
debouce is only called once on the initial run, it creates and returns a new anonymous function - the actual event handler.
When the input event is triggered, the previously created function is executed and will call func (onInput) after 500ms. func is only once passed to debounce, but args are the actual input event arguments, which will be passed on to func via apply. In this case, apply is basically the same as func(...args); So func (aka onInput) will be called with the actual arguments from the input event after 500ms.
This is an example of debounce.
Debouncing is a practice which is used to improve browser performance.
A programming practice which ensure that time-consuming tasks do not fire so often.
It is used to limits the rate at which a function gets invoked.
I have explained debounce with example, please check out the link
debounce
Related
Wanted to see if experts here help explain how to understand the below debounce logic better. I got this from an Udemy course but the video only got so much explanation. From the code below.. this is what I understand it does - everytime an "input" is detected setTimeout inside debounce function will execute and after 1 second it'll remove the timeout.
How does the spread operator and the "args" come into play in this?
I understand the spread operator takes in an array and then "spreads" it out as separate arguments into the function parameter. Am I misunderstanding how the func.apply works here? How does the return(...args) read the input value arguments?
It seems like "onInput" is func and the return values from "onInput" is passed as arguments to ...args?
const debounce = func => {
let timeoutID;
return (...args) => {
if(timeoutID) clearTimeout(timeoutID);
timeoutID = setTimeout(
() => func.apply(null, args),
1000
);
};
}
const onInput = event => {
fetchData(event.target.value);
};
input.addEventListener("input", debounce(onInput));
A few things to clarify:
debounce returns a (anonymous arrow) function. It doesn't do much more than that, except that it provides a closure for the variables func (the argument passed to debounce) and timeoutID. So when you call debounce(onInput) the returned function will know about onInput.
The above-mentioned returned function becomes the handler for the input event. So when that event triggers that anonymous arrow function is called with the event object as argument. So args will be [event object]. This anonymous function will clear any pending timer event and will schedule a new one that will call func.apply(null, args).
When the timer expires without being cleared, then func.apply(null, args) will be called. We know what func is: onInput and we know what args is: [event object]. So that means we effectively call onInput with the event object as argument.
As to your questions:
How does the spread operator come into play in this?
It is the rest syntax, and allows to capture all the arguments into one array.
How does the "args" come into play in this?
As explained above, as the event handler is called with one argument, args will be initialised to an array with the same arguments that the event handler would get, i.e. with the event object.
Am I misunderstanding how the func.apply works here?
All you wrote about it is that the function will execute. apply is a method that calls the function with a specific value for this (which is not the goal here, so just null is provided), and with an array that should be used as arguments in the call. As args is exactly that array of arguments we got, and we just want to pass them on, that is what is passed here as well.
It should be said that in modern JavaScript you'd achieve the same result with func(...args);
How does the return(...args) read the input value arguments?
First of all that is not the complete statement. The complete statement includes the whole arrow function, which is the object that is returned here. Like explained above, debounce returns a function (object).
This code "only" returns that function, it does not read input value arguments. It provides the function that will later do this. Realise that debounce is called now, while that returned function is only called when the event fires.
Rewritten...
It may clarify things when rewriting the code in a slightly different way. I hope it better highlights the difference between returning a function and executing it. This can happen at different times.
function debounce(func) {
let timeoutID;
// Define a local function. Don't execute yet.
// It takes any arguments, as it will just remember them
// for passing them to the original function later on (after timer).
function debouncedFunc(...args) {
// If we had a pending timer job, clear it, as we want a new one.
if (timeoutID !== undefined) {
clearTimeout(timeoutID);
}
// Create a function to execute later. It should itself
// execute func with the arguments we already know about.
function executeFunc() {
// This is the more modern syntax to do func.apply(null, args):
// It is easier to read; we just call func with some known arguments
func(...args);
}
// Schedule that function to run later, and get a handle for that job
timeoutID = setTimeout(executeFunc, 1000);
}
// Return the new function object to the caller.
// They can call it with some arguments, or let
// some other API call it for them (like with addEventListener)
return debouncedFunc;
}
function onInput(event) {
fetchData(event.target.value);
}
// Get a function object
const debouncedInputHandler = debounce(onInput);
// Make that function the event handler
input.addEventListener("input", debouncedInputHandler);
When I run the code:
$(".pro-tip-1").mouseover(activateProTip(1));
It calls the function activateProTip right away. It doesn't wait for the mouseover to be a true scenario.
Now if I take out the argument (1) being passed, it runs as intended. It waits for mouseover to be true then it calls the function. This is what I want, however I also want to pass an argument.
$(".pro-tip-1").mouseover(activateProTip);
The problem is I can't seem to pass an argument and have it run as intended, but I want to be able to pass an argument.
I am completely new to Javascript if that isn't already obvious so please keep your code in response simple to follow, thanks in advance!
Try this solution it will work
$(".pro-tip-1").mouseover(()=>activateProTip(1));
Explanation:
you can use always callback function for click events.
when you calling like this(activateProTip(1)), this will not binding events, that's why it will call the immediatly
This is expected, the required argument is a function. If you instead pass a statement, it will be interpreted immediately (potentially you could have called a function which actually returns a function that you want to call on mouseover!). You can instead write a function that will then call activateProTip with the argument.
$(".pro-tip-1").mouseover(() => activateProTip(1));
I want to pass arguments to an event listener in Javascript.
I have found solutions however I cannot understand why or how they work and why other solutions do not work.
I have a C/C++ background, however in Javascript functions perform a lot different.
Could you please help me understand how and why the following examples work or not work?
Without parameters the code works fine:
var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction);
function eventFunction()
{
console.log("works");
}
If I include brackets on the eventListener the function executes once without the event firing and then does nothing:
var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction());
function eventFunction()
{
console.log("works");
}
I suppose this is because the function is invoked at the eventListener and this doesn't allow the eventListener function to call the eventFunction later.
When I want to pass an argument with the eventFunction.
The following does not work:
var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));
function eventFunction(myStr)
{
console.log(myStr);
}
It invokes the eventFunction without the event firing and then when the events fires does nothing which is the same behaviour as previously.
So far I think I can understand.
To pass the argument correctly in the event function I found the following code.
The following solution works fine:
var clicker = document.getElementById("mainNavToggle");
clicker.addEventListener("click", eventFunction("works"));
function eventFunction(myStr)
{
function func(event, myStr)
{
console.log(myStr);
}
return function(event) {
func(event,myStr)
};
}
The first thing I notice is that this eventFunction is not invoked immediately.
Why is that?
However, I am at a loss of how arguments are passed within each function.
I understand that the "works" literal is passed to myStr on the eventFunction.
However in the function func there is an additional event parameter not passed by eventFunction.
Also why does the eventFunction needs to return another function with one parameter that internally calls the func function?
Also please notice that I want to pass parameters to the eventFunction that do not have a global scope, otherwise there would not be a need to pass parameters.
Let's dissect this step-by-step.
General information
The .addEventListener function/method takes in 2 (or 3) arguments:
a String, with a value of the event type/name (for example "click")
a pointer to a Function, which should be executed when the event occurs
a Boolean, specifying if event bubbling or event propagation should be used. This argument is optional and can be omitted.
Example 1
In you first example, you pass a String ("click") and a pointer to a Function (eventFunction) into .addEventListener. Everything works as expected, the event occurs and the function is executed.
Example 2
In this example, you pass a String and undefined to .addEventListener, which is not what .addEventListener expects. You might ask yourself "When did I pass in undefined?". Well, it happened as soon as you executed your eventFunction by adding parens () after it. Here, the syntax in JS is equal to the syntax in most other languages, adding parens to the right side of a function executes the function.
Because your eventFunction doesn't return anything explicitly, it automatically returns undefined. Therefor, this is what .addEventListener got:
clicker.addEventListener("click", undefined)
However, because you executed eventFunction, it logs "It worked" to the console once.
Example 3
This example fails for the same reasons example 2 failed.
Example 4
The code in the last example works, because it uses a concept called closure. There are literally thousands of explanations of the concept, so my explanation here will be really short. If you have trouble understanding it, just google for
"javascript closures".
In contrast to a lot of other languages, JavaScript has function scoping instead of block scoping. So if you define a variable inside a function F and return another function G from within F, G will have access to variables and arguments from inside F. For demonstration purposes:
function F () {
var fVariable = 'Defined in F';
return function G () {
return fVariable; // <-- this is the closure
}
}
var funcG = F(); // <-- execute F
funcG(); // -> 'Defined in F';
Compare this short example with your fourth code: They are pretty much the same. The only difference is, that your code creates an extra function func.
Now, if you call clicker.addEventListener("click", eventFunction("it works")),
you execute eventFunction, which returns another (anonymous/lambda) function which encapsulates the "it works" string via a closure. If we write it out by hand, this is what .addEventListener "sees":
clicker.addEventListener("click", function (event) {
func("it works", event);
});
EDIT: Solving the problem
Here's a working example, note that I changed the function names to reflect their purpose:
function eventHandlerFactory (myStr) { // <-- eventFunction in your code
return function executeOnEvent (event) { // <-- executed if an event occurs
console.log(myStr);
console.log(event);
}
}
clicker.addEventListener("click", eventHandlerFactory("it worked"));
The eventHandlerFactory function returns a function executeOnEvent, which is passed into .addEventListener. Writing it out by hand again, this is what the interpreter understands:
clicker.addEventListener("click", function executeOnEvent (event) {
console.log("it works");
console.log(event);
});
The first thing i notice is that this eventFunction is not invoked
immediately
It is invoked immediately. However, it returns a new function. This is the function that is registered for the click handler. This function, when called, calls the function func in a closure. The arguments passed to this function are also preserved in a closure.
To understand this concept, you need to understand how closures work. This is a topic that has been written about extensively, so I'll just point you to How do JavaScript closures work?.
Please explain me the difference between these two statements. which one is calling the function 'connect'. connect is a user defined function.
`peer.on('connection', connect);`
and
f.on('open', function() {
connect(f);
});
Both will call connect when the event occurs. The main difference is that the first one gets its arguments set by the event subsystem since it is called directly by whatever manages the events. If your function either doesn't use any arguments or its arguments match up exactly with what the event system passes, then the first one works fine.
In the second one, you control the arguments sent to connect(f) so you can make the arguments anything you want. So, if you want to control the arguments yourself, then the second block of code gives you that option.
There really isn't much of a difference aside from example one using a named function as the callback and the second example using an anonymous function as the callback. Named callbacks are useful if you need to reuse them or if you just want to have more control over the organization of your callbacks.
Either way, the functions will be called after the execution of 'on' is complete.
For more information about callbacks have a look at http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
bunny.mousedown = function(mouseData){
text.setText(mouseData.global.x);
}
The 'setText' part gets called when someone presses on the bunny sprite. I'm using PIXIjs.
Hello, I'm new to JS and having a bit of a hard time understanding this code. As I understand, everything in JS is an object, including functions. In other languages that I've had experience with, you'd just use event listeners with this kind of thing.
Mousedown is a callback function, or so it says in the documentation. I think I understand what's a callback function. But, I'm confused at how it's implemented in the code above.
function display(s , callb){
alert(s);
callb(1 , 2);
}
function add(q, r){
alert((q + r).toString());
}
display("amidoindisrite?", add);
callb would be the callback function, I think... But, anyway, I don't understand how the code on the very top gets executed/called. Anyone have any ideas? What would be the equivalent in Java or Python if there is one? Thanks.
In your second example, callb is a pointer to a function, or the function definition if you like. If you apply the parentheses after it, it executes the function with the parameters provided (if any, integers 1 and 2 in this case). Other ways to execute a callback are the call() and apply() methods.
In the first example, the mousedown property expects a value that is a callback, i.e. the function definition. This example defines a function that assigned to this mousedown property. When the mousedown event is triggered for the bunny object, the mousedown property is executed (using parentheses, call() or apply(), that would depend upon the Pixjs library). That property being the function defined, the text.setText method is run.
I hope that clarifies it.