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.
Related
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.
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
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.
I'm curious why:
(function () { return 'one' })()()
returns:
TypeError: (intermediate value)(...) is not a function
and not:
TypeError: 'one' is not a function
Error messages use variable names or other identities to say what is not a function. Because the return value hasn't been assigned to anything, it doesn't have an identifier, so the engine says intermediate value
The documentation of the error message "TypeError: "x" is not a function" explains:
What went wrong?
It attempted to call a value from a function, but the value is not actually a function. Some code expects you to provide a function, but that didn't happen.
It also provides some code examples that triggers this error and the actual error message reported by them. I won't copy them here but please take a closer look on them and notice the error messages they generate.
The "x" part is replaced in the actual error messages by the name of the object that is expected to be a function and it is not.
Because the object in this case does not have a name (it is an intermediate result computed during the evaluation of the expression, see the explanation below), the engine cannot report its name and tries to be as helpful as it can. It reports "(intermediate value)(...)" probably because this way it is more descriptive; it is a value returned by a function that is not stored but used for computation of another value.
It cannot report the actual value instead because the intermediate value can be anything; if it is a complex data structure then the error message becomes bloated without adding much information.
Apparently I didn't understand the question from the first time, what follows is my initial answer that explains why the error is generated, not why the error message is what it is and not what the OP expects.
This code ...
(function () { return 'one' })()()
... creates an anonymous function...
function () { return 'one' }
... calls it...
(function () { return 'one' })()
... then attempts to interpret the value returned by the function as another function and call it:
(function () { return 'one' })()()
The function created on step #1 returns a string ('one') when it is invoked (on step #2).
On step #3, the effect of the code is the same as calling 'one'(). This is not the same as one() (as you might think).
The intermediate value referred in the error message is the string returned by the first function call that is then used in the expression (as a function) without being saved in a variable (that's the explanation of the "intermediate" wording.)
As the error message clearly says, 'one' is not a function and attempting to use it as a function (by placing the second pair of parenthesis in the expression) doesn't work.
In order to make it work, the anonymous function created on step #1 must return another (anonymous) function, like this:
(function() { return function() { return 'one'; } })()()
Now, when it is called, the outer function returns an anonymous function that is similar with the anonymous function created on step #1 by the original code. When this function is called (the second ()) it returns the string 'one'.
This is probably not what you wanted. Calling a function given its name as string is possible only by using eval() which is language feature that is best to avoid (for several strong reasons.)
Because when in braces () it (function () { return 'one' }) becomes an expression which yields intermediate results and those results are not yet bound to a variable yet.
As per spec,
Specification type values are specification artefacts that do not
necessarily correspond to any specific entity within an ECMAScript
implementation.
Specification type values may be used to describe intermediate results
of ECMAScript expression evaluation but such values cannot be stored
as properties of objects or values of ECMAScript language variables.
I'm curious, is there any difference between the two functions below?
Is one just passing a function inside an anonymous function when ready whereas the other is passing an actual named function when ready?
Example:
<p>Not loaded yet.</p>
First method:
function newName() {
$( "p" ).text("The DOM is now loaded and can be manipulated.")
}
$(document).ready(function() {
newName()
});
Second method:
function newName() {
$( "p" ).text( "The DOM is now loaded and can be manipulated.")
}
$(document).ready(newName());
Is one more correct than the other?
Is one just passing a function inside an anonymous function when ready whereas the other is passing an actual named function when ready?
Yes and no.
I'm curious, is there any difference between the two?
The first is passing an callback function that is executed when the event fires. When that even fires is explained here.
The latter passes the resolved return value (which is undefined because newName has no return statement), which isn't the same as the second. The reason it passes the return value to ready is because you invoke the function immediately (which may seem like it works), which then passes the return value. To make them functionally equivalent, do:
$(document).ready(newName);
This will pass a function reference, and won't invoke it. Also, as mentioned before, invoking as ready(func(); func2();) is not valid syntax.
Effectively there’s no difference between
$(document).ready(function(){
newName();
});
and
$(document).ready(newName);
There’s a small technical difference: in the first snippet, an anonymous function calling newName is passed, in the second snippet, the named function newName itself is passed.
Functions are just callable objects that can be referenced by their name or the name of a variable holding the function.
Note that $(document).ready(newName()); is calling newName — immediately — and passing the return value to ready. This only makes sense if newName returns another function, which in this case it doesn’t.
The title also mentions something like $(document).ready(newName){}. I’m assuming that’s a typo, since that’s not valid syntax.
$(document).ready(newName(); otherName(); otherName1()); also isn’t valid syntax.