Why there isn't parentheses for methods inside of promises? - javascript

Why there is no parentheses for console.log inside of then block of promise?
How does it know that what should it log?
const Category = require('./models/category');
const cat = Category.find({}).then(console.log);

It's passing a function reference as a callback. console.log refers to a function to be called when the promise resolves as opposed to actually calling console.log.
Functions are first-class objects in JavaScript. They can be passed around. Just like you would do then(x => console.log(x)). If you call it before-hand, it will be necessarily evaluated before (and its return value passed):
promise.then(console.log()) // Called immediately, undefined passed to then
Note that it's not exactly the same as then(x => console.log(x)). Any context is lost because the callee has no way to recover that from just a function reference. Though this doesn't have an effect here AFAIK.

This is a reference to the function that will be called after Category.find(). The value passed to it will be the result of the find.

Calling console.log() inside the then callback would output nothing in the console. Usually, you pass an anonymous or arrow function to the callback argument, but since console.log can pretty much have anything as a parameter, you just have to pass the name of the function so the Promise can execute it later.

Related

Passing argument in Promise.prototype.then()

While going through a topic on MDN Web Docs I came across an example
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
var promise1 = new Promise((resolve, reject) => {
resolve('Success!');
});
promise1.then(function(value) {
console.log(value);
// expected output: "Success!"
});
I am a beginner in JS and my doubt is regarding the argument being passed in the function inside the promise1.then()
We earlier passed the string 'Success!' in the resolve() method. But we did not specify before-hand what data we are assigning to the value variable (which is being passed in the console.log() ). Intuitively, shouldn't we have explicitly defined var value = /* Data from Promise.resolve() */ for first defining what the data value carries and subsequently passing it in console.log()?
Otherwise, I can just change the name value to anything, say, myVar and get away with the same result: logging "Success!" to the console.
I tried Googling it but it wasn't helpful as I do not know what topic of JS my question pertains to. So, please do suggest relevant material. Thanks!
We earlier passed the string 'Success!' in the resolve() method. But we did not specify before-hand what data we are assigning to the value variable (which is being passed in the console.log() ).
The value that is passed to a function argument is determined when you call the function.
The code that calls it is part of the Promise library (i.e. written by someone else). They specified what it should be.
Intuitively, shouldn't we have explicitly defined var value = /* Data from Promise.resolve() */
No. The people who wrote the Promise library already did that.
Otherwise, I can just change the name value to anything
Yes. The names of arguments don't determine the values of what is passed into them. The positions do.
value is just a name you gave the first argument to the .then() handler callback function. You can name it anything you want. Whatever name you give it, it will get the value of the first argument to the .then() handler. That's true for all functions. You can name the arguments whatever you want and it does not change what value they get when they are called.
Otherwise, I can just change the name value to anything, say, myVar and get away with the same result: logging "Success!" to the console.
Yes, you can make the name of the argument anything you want. Whatever name you give it, it will receive the first argument from when the function is called. It is the caller who determines what value the argument will have. It is the function declaration that determines what name that first argument will have inside the function so that you can refer to that first function argument.
In this case, the function is called by the internals of the promise library and when it calls the .then() callback function, it passes as the first argument the resolved value of the promise which your case is your "Success!" string.

functions returned from other functions in javascript

I am new learner of Javascript and I got stuck in "functions returned from other functions".
The code is as below.
var createScream = function(logger) { return function(message) {
logger(message.toUpperCase() + "!!!")
}
}
const scream = createScream(message => console.log(message))
scream('functions can be returned from other functions')
scream('createScream returns a function')
scream('scream invokes that returned function')
Console output:
"FUNCTIONS CAN BE RETURNED FROM OTHER FUNCTIONS!!!" "CREATESCREAM
RETURNS A FUNCTION!!!" "SCREAM INVOKES THAT RETURNED FUNCTION!!!"
Question: why it will work this way? what is the process of executing?
Does function scream have any parameter? how does it work?
This may be very easy, I searched but no clear explanation.
Can someone please give me a hint or explain the whole execution process in details?
Thanks in advance!
First, Higher order functions are not about functional languages. Functions that operate on other functions i.e. taking a function as an argument and returning another function, are called higher order functions.
Your snippet:
You created an anonymous function with argument logger, which returns another anonymous function and bind that to variable createScream.
Then you called createScream with a function as an argument. storing the returned value in const scream. At this time you are returned a function with argument logger being the fat arrow function you passed.
Now you called scream with strings. Remember scream is also a function because in the earlier step the function call returned another function. That function has access to logger argument passed to the outer function. This is an example of closure.
When you call scream with strings. The returned function is called which is logging the message in uppercase plus !!!.
It will take sometime to get what is happening here, If you have limited programming experience. Read about higher order functions, lexical scope, closure.
In JavaScript and other functional languages, you will hear the term that functions are "first-class citizens" meaning that functions can be passed around as values or referenced by other functions.
It's normal for this to take a bit of time to grok, but try to walk through your code step by step and you'll get it:
The createScream function accepts a function as input (logger)
The createScream function then returns another function that accepts its own input (message)
The returned function uses the original input function (logger) as well as the second input (message)
And consider the execution order in usage as well:
scream invokes createScream with a console.log function
now when you invoke scream with a message, that message will first be changed as per the definition in createScream
then once the message is changed, it is invoked by the logger function console.log

In js when returning a reference to a this value vs passing the this reference keyword, is there a difference in binding time?

I'm trying to understand the below code which prevents bugs caused by a function silently passing to a call back function more arguments that aren't wanted in the parameters of the callback function:
["1","2","3"].map(parseInt)
returns [1, NaN, NaN] because the index gets passed as a second parameter to parseInt which accepts it as the radix, so the array values are invalid. To solve it, the author of this blog post suggests a js extension:
Function.prototype.only = function(numberOfArgs) {
var self = this; //the original function
return function() {
return self.apply(this,[].slice.call(arguments,0,numberOfArgs))
}
};
Which would be called like so:
["1","2","3"].map(parseInt.only(1))
I'm struggling to understand why "this" is passed as a function parameter while self is returned as a reference to this. They both point to parseInt correct? Is there a difference in binding times of parameters vs return values?
They both point to parseInt correct?
No.
The value of this depends on how a function is called.
The function passed to map gets called by the internals of map.
Look at the documentation for map.
If a thisArg parameter is provided to map, it will be used as callback's this value. Otherwise, the value undefined will be used as its this value.
So if the returned anonymous function used this instead of self it would be calling undefined.apply not parseInt.apply.
I'm struggling to understand why "this" is passed as a function parameter while self is passed as a reference to this. They both point to parseInt correct?
No. self will refer to parseInt. this will be whatever this the function was called with, which could be anything. In your example:
["1","2","3"].map(parseInt.only(1))
...this will either be a reference to the global object (in loose mode) or undefined (in strict mode), because map will use undefined when calling the callback (which is turned into a reference to the global object in loose mode).
There are several ways this might be something else though:
If a second argument were passed to map:
["1","2","3"].map(parseInt.only(1), {})
// Second argument -----------------^^
...it would use that value rather than undefined when calling the callback.
If Function#bind were used on the function only returns:
["1","2","3"].map(parseInt.only(1).bind({}))
// Bind ---------------------------^
...then this would be that value.
If the function only returns were called with call or apply (which is what map does, so this is kind of a repetition of #1 :-) ), the value supplied for this would be used.

what's the difference between calling a function and passing a function?

This conversation came up at work today and I wasn't completely able to grasp the difference, and my google search so far has been fruitless.
The example that was used at work was the difference between
DoSomethingFunction().then(function(){
DoSomethingElse();
});
and
DoSomethingFunction().then(DoSomethingElse());
To me, I look at the first, and it's an anonymous function, so that would just get called and inside it, is the function we want to call, but that's why I used the second version, which just calls the function without wrapping it in a separate function.
Can somebody explain the difference to me?
Functions in JavaScript are objects, and can be passed around just like any other object. DoSomethingElse is a function object that can be executed with DoSomethingElse().
.then expects a function object, so the following just executes the function and returns its value or undefined if it returns nothing:
// this is wrong, unless `DoSomethingElse` returns a function
DoSomethingFunction().then(DoSomethingElse());
The following passes an anonymous function (this is what .then expects, a function), then executes DoSomethingElse inside.
DoSomethingFunction().then(function(){
DoSomethingElse();
});
The following passes the function object to then, and does the same as the above:
DoSomethingFunction().then(DoSomethingElse);
Passing a function means, that a function is passed as an argument, and it can be called in the called function. Calling a function means that the function body is executed, and it returns a value. In your example
DoSomethingFunction().then(DoSomethingElse());
you pass the result of a function call, so the result of calling DoSomethingElse (the return value).
In case of
DoSomethingFunction().then(DoSomethingElse);
you pass a function, which then needs to be executed in the then function to get it's result.

what is the difference between these two

I'm very new to js so I'd appreciate some help. I have two blocks of code that I think should work identically but don't. Can someone explain how they're different? It looks like in the first piece of code, the parser enters the function directly.
function embedGameSwfAfterReg() {
embedGameSwf("{$swfLocation}", "100%", "100%", {$flashVars});
}
API.registerOnload(embedGameSwfAfterReg())
and
API.registerOnload(function() {
embedGameSwfAfterReg("{$swfLocation}", "100%", "100%", {$flashVars});
});
In the first code block, you're registering the result of the embedGameSwfAfterReg function (undefined) as the onload function (() means you're evaluating the function). Remove the parentheses to have the embedGameSwfAfterReg function itself registered:
API.registerOnload(embedGameSwfAfterReg)
This
API.registerOnload(embedGameSwfAfterReg())
runs embedGameSwfAfterReg, and then passes the return value (undefined since it doesn't return a value), to registerOnLoad
you want
API.registerOnload(embedGameSwfAfterReg)
which passes the function itself to registerOnload
Functions are objects in Javascript and can be passed directly by their names. When you add the parens, it instead runs the function and passes the result.
function embedGameSwfAfterReg() {
embedGameSwf("{$swfLocation}", "100%", "100%", {$flashVars});
}
API.registerOnload(embedGameSwfAfterReg)
and
API.registerOnload(function() {
embedGameSwfAfterReg("{$swfLocation}", "100%", "100%", {$flashVars});
});
would work the same way.
The difference is () which you have put with embedGameSwfAfterReg function in the first case
It actually calls the function there only but its different in the 2nd case.
I'm asssuming that the second example should be
API.registerOnload(function() {
embedGameSwf("{$swfLocation}", "100%", "100%", {$flashVars});
});
If so, then the difference is quite big. In the first case, the embedGameSwfAfterReg function is invoked and the embedGameSwf is called when you register. This is probably not what you want since the the return value of the function is undefined.
In the second case, the anonymous function is not invoked until later when the registerOnLoad event is raised. This is probably what you want.
API.registerOnload() takes a callback function as parameter, therefore you only have to pass in the function name as reference, otherwise the function is directly getting called when the code runs.
// Correct form is:
API.registerOnload(embedGameSWFAfterReg)
Your second sample already is an anonymous function that is handled like an function callback and therefore evaluated when API.registerOnload(callback) is calling the reference with callback() somewhere inside it's code.
Short answer:
First piece of code do nothing, because embedGameSwfAfterReg doesn't have a return statement. Probably it could even end up with an error if API.registerOnload doesn't accurately check its arguments before execution.
Second piece of code creates an anonymous-function that is passed as an argument to API.registerOnload method which (as far as I can see from method name) runs functions during an Onload event.
Long answer:
In the first piece of code you declare a new function named embedGameSwfAfterReg which resists in global-scope of your code:
function embedGameSwfAfterReg() {
// calls embedGameSwf function
}
after, you execute defined function and pass the result to registerOnload method of an object named API:
API.registerOnload(embedGameSwfAfterReg());
As you probably mentioned, declared function embedGameSwfAfterReg has no return statement, so the result of its execution will be undefined. In other words
API.registerOnload(embedGameSwfAfterReg());
is doing the same as
embedGameSwfAfterReg();
API.registerOnload();
so eventually it calls API.registerOnload() WITHOUT any arguments passed!
Second piece of code creates an anonymous function (functions are specific objects in JS, which can be passed to other functions/methods, have its own methods and executed). Then it passes created function (or better say a reference to the function) to registerOnload - method of an object called "API".
You should read topics about Objects, Function-type, scopes, anonymous functions and closures in JS. I would advise Mozilla JavaScript guide
Also feels free to play with a simplified example at jsfiddle which gives some practical hint on anonymous functions in JS.

Categories