Javascript Arrow calling a function from another with functionName() vs ()=>functionName - javascript

Let's say you have a method/function which you did not want to call until runtime.
const someMethod = () => {
document.getElementById("myField").value = "Hello";
}
What is the term for and what is the difference between how these are executed.
this.check(() => someMethod);
AND
this.check(someMethod())

They're entirely different.
this.check(() => someMethod); will pass a callback which, when called (if ever), returns a function.
this.check(someMethod()) will call someMethod immediately, then pass the result to the this.check method.
Another option not listed is this.check(() => someMethod());, which will call someMethod when the callback passed to check is called.
If the this context is something you're worried about, then:
this.check(someObj.someMethod)
will result in someMethod, when invoked, to be invoked with a this of whatever the check method wants it to be. It does not preserve the context of someObj. In contrast
this.check(() => someObj.someMethod())
will result in someMethod being invoked with a this of someObj, regardless of how check tries to call it.
So, usually, to be safe, you'll want this.check(() => someObj.someMethod()) - or bind someMethod in advance, or declare someMethod with an arrow function instead of a function.

Here: this.check receives a callback as its paramter which returns the someMethod function.
this.check(() => someMethod);
And in this case: this.check receives the value that someMethod returns as its parameter.
this.check(someMethod())

Related

How the callback is executed in this function?

const getData = (cb) => {
setTimeout( () => {
cb({ data: ['there', 'is', 'stuff', 'here'] })
}, 100)
}
getData( data => {
console.log(data);
});
Here is the example of the javascript callback. Could some one let me know how this functions is executed into the javascript callback?
Here what is the function inside getData(cb) ? How it will be executed ? How the functions is passed as callback inside cb and return to the console.log
Regards.
The function inside getData is a callback being passed to setTimeout, which is one way to schedule a call to a function to happen in the future. In this case, it's asking for that callback to happen roughly 100ms later. getData returns before that happens.
The setTimeout callback is a closure¹ over the context where it's created, which means it has access to cb even after getData has returned. So when the browser's timer calls the callback, the callback can call cb. The call to cb uses an object literal to create an object to pass to cb.
In the call to getData, the author is passing a function as cb that logs the data it receives.
So:
getData is called, passing in a function that will log the argument it gets.
getData calls setTimeout to schedule a callback in about 100ms, passing in another function for the timer to call.
getData returns.
About 100ms later, the browser's timer subsystem triggers a call to the callback passed to setTimeout.
That callback creates an object and calls cb, passing the object to it.
That callback (the one passed to getData) logs the data object it receives.
¹ "closure" — see: SO, my anemic blog
In order to understand the code you can just simplify it by naming the anonymous functions. One example could be:
function logData(data) {
console.log(data);
}
const getData = (cb) => {
// `cb` is `logData` function when `getData` is called
function timeoutCallback() {
var data = { data: ['there', 'is', 'stuff', 'here'] };
cb(data);
}
setTimeout(timeoutCallback, 100)
}
getData(logData);
Does that make sense?
1- first global execution context created
2- get data function will be called then it will wait for 10 seconds inside the event loop then it will be come to execution context and printed to console.

JavaScript Get Function Instance with Arguments Passed In

Say I have the following code.
function myFunc(item) {
console.log(item);
}
function action() {
return myFunc("Hello World");
}
const myUncalledFunction = action;
myUncalledFunction(); // will console.log "Hello World"
Is there a way to make this code cleaner? I've looked into .apply() but it looks like that calls the function immediately as well.
The reason I'm wanting to do this is Chai's expect for throw requires you to pass in an uncalled function. But the function I'm wanting to test requires arguments to be passed in. So currently I just created a wrapper function that returns the function with the arguments passed in.
I feel like there has to be a better way to achieve this that is cleaner and simpler for someone looking at it.
Use .bind to bind arguments (and a calling context, if needed) to a function, which produces a new callable function in the process. Here, you can see this as basically allowing you to pass in arguments at one time, and then call the desired function with those arguments later:
function myFunc(item) {
console.log(item);
}
const myUncalledFunction = myFunc.bind(undefined, 'Hello World');
myUncalledFunction();
Or you might just use a concise arrow function
function myFunc(item) {
console.log(item);
}
const myUncalledFunction = () => myFunc('Hello World');
myUncalledFunction();

Is `setState({key: value}, () => function())` the same as `setState({key:value}, function())`?

Is there any difference between using React's setState() method in the following two ways:
setState({key: value}, myFunction())
vs.
setState({key: value}, () => myFunction())
(edited to use myFunction as in the post).
The two lines of code are quite different:
setState({key: value}, myFunction())
calls myFunction when the arguments are being evaluated, before calling setState. The return value of myFunction is then passed to setState as its second argument. So this version is only useful if myFunction() returns a callback function for use by setState. If myFunction is the callback, however, then it's a bug which could manifest itself as the callback being called prior to the state being updated instead of afterwards.
setState({key: value}, () => myFunction())
creates an anonymous call back function which when executed returns the return value of calling myFunction. The arrow callback function is passed as the second argument to setState, without calling myFunction in the process. myFunction will then be called after setState has updated the state and called the arrow function.
The second form is generally better written without creating an anonymous function intermediary:
setState({key: value}, myFunction)
Although possibly unrelated to the question, an arrow function could be used to set the this value of myFunction to the this value prior to the call to setState:
setState({key: value}, ()=>this.myFunction); // use current this value in the callback.

Why can I not pass a function call (rather than a function reference or an anonymous function) to setTimeout()?

Please ignore the fact that this code achieves nothing and apologies for what's probably an inane question!
I understand that I cannot pass a function call into setTimeout() as the first argument, but why can I not do that?
let names = ['Andy', 'Ross', 'David'];
function printer (name) {
console.log(name);
}
names.forEach(name => setTimeout(printer(name), 1000);
Result:
Andy
timers.js:327
throw new TypeError('"callback" argument must be a function');
^
I can solve the problem by instead using a reference to printer and using bind() to send name along with it, but why must I take these extra steps?
let names = ['Andy', 'Ross', 'David'];
function printer (name) {
console.log(name);
}
names.forEach(name => setTimeout(printer.bind(null, name), 1000));
Result:
Andy
Ross
David
This is because of the order of execution. If you pass a function call to setTimeout, the function will be executed immediately, i.e. the function is put on javascript's execution stack immediately.
If you pass a function name, i.e. a reference to a function, the function is only put in the javascript thread's execution stack once the timer finishes.
you can try this:
setTimeout(function(){printer(name)}, 1000)
setTimeout should take a function as its first argument.
Please refer:
https://www.w3schools.com/jsref/met_win_settimeout.asp
Here you are passing the result of the function as the first argument which is undefined.
You can do it like this:
setTimeout(printer, 1000, name)
The correct way of passing a function reference is to use callbacks.
names.forEach(name => setTimeout(function() {
printer(name);
}, 1000));
callbacks contains reference to the function.
setTimeout(callbackFunction, milliseconds);

Why is 'this' undefined inside class method when using promises? [duplicate]

This question already has answers here:
setTimeout and "this" in JavaScript
(5 answers)
Closed 7 years ago.
I have a javascript class, and each method returns a Q promise. I want to know why this is undefined in method2 and method3. Is there a more correct way to write this code?
function MyClass(opts){
this.options = opts;
return this.method1()
.then(this.method2)
.then(this.method3);
}
MyClass.prototype.method1 = function(){
// ...q stuff...
console.log(this.options); // logs "opts" object
return deferred.promise;
};
MyClass.prototype.method2 = function(method1resolve){
// ...q stuff...
console.log(this); // logs undefined
return deferred.promise;
};
MyClass.prototype.method3 = function(method2resolve){
// ...q stuff...
console.log(this); // logs undefined
return deferred.promise;
};
I can fix this by using bind:
function MyClass(opts){
this.options = opts;
return this.method1()
.then(this.method2.bind(this))
.then(this.method3.bind(this));
}
But not entirely sure why bind is necessary; is .then() killing this off?
this is always the object the method is called on. However, when passing the method to then(), you are not calling it! The method will be stored somewhere and called from there later. If you want to preserve this, you will have to do it like this:
.then(() => this.method2())
or if you have to do it the pre-ES6 way, you need to preserve this before:
var that = this;
// ...
.then(function() { that.method2() })
Promise handlers are called in the context of the global object (window) by default. When in strict mode (use strict;), the context is undefined. This is what's happening to method2 and method3.
;(function(){
'use strict'
Promise.resolve('foo').then(function(){console.log(this)}); // undefined
}());
;(function(){
Promise.resolve('foo').then(function(){console.log(this)}); // window
}());
For method1, you're calling method1 as this.method1(). This way of calling it calls it in the context of the this object which is your instance. That's why the context inside method1 is the instance.
Basically, you're passing it a function reference with no context reference. The this context is determined in a few ways:
Implicitly. Calling a global function or a function without a binding assumes a global context.*
By direct reference. If you call myObj.f() then myObj is going to be the this context.**
Manual binding. This is your class of functions such as .bind and .apply. These you explicitly state what the this context is. These always take precedence over the previous two.
In your example, you're passing a function reference, so at it's invocation it's implied to be a global function or one without context. Using .bind resolves this by creating a new function where this is explicitly set.
*This is only true in non-strict mode. In strict mode, this is set to undefined.
**Assuming the function you're using hasn't been manually bound.
One way functions get their context (this) is from the object on which they are invoked (which is why method1 has the right context - it's invoked on this). You are passing a reference to the function itself to then. You can imagine that the implementation of then looks something like this:
function then( callback ) {
// assume 'value' is the recently-fulfilled promise value
callback(value);
}
In that example callback is a reference to your function. It doesn't have any context. As you've already noted you can get around that by binding the function to a context before you pass it to then.

Categories

Resources