I have started learning promises in JS, and there are (resolve, reject) which are passed to promise. After some actions in the function you call resolve() if there is everything OK and reject() if not. So, that's why I am asking about this.
Can we actually call the parameters of a function inside of it? Actually, if I put () after the parameter inside a function in VS Code, it is highlighted as a function.
Sorry, if there is some issues with explaining. I am not a native speaker...
There is an example: (what is stack() actually?)
const iGotIt = true;
const f = (stack, overflow) => {
if (iGotIt) {
stack({
newKnowledge: 'Finally',
message: ':)'
})
}
}
It depends on the function parameter, since it may not be a function.
For example:
myFunction(data, callback){
const result = do_something_with_data();
callback(result);
}
myFunction(0, result => {
do_something_with_result();
}); //works
myFunction(1, console.log); //works
myFunction(2, 0); //doesn't work, 0 is not a function.
what is stack() actually?
It's the first parameter in the f function.
The f function expects the first parameter to itself also be a function, and one which accepts at least one parameter which is an object.
But what stack actually is depends on what gets passed to f.
For example, consider this usage in which a function is passed as the first parameter:
const iGotIt = true;
const f = (stack, overflow) => {
if (iGotIt) {
stack({
newKnowledge: 'Finally',
message: ':)'
})
}
}
f(x => console.log(x));
Then invoking stack() invokes the function that was provided. Alternatively, consider this example:
const iGotIt = true;
const f = (stack, overflow) => {
if (iGotIt) {
stack({
newKnowledge: 'Finally',
message: ':)'
})
}
}
f();
This fails because nothing was provided, so stack is undefined. Or this example:
const iGotIt = true;
const f = (stack, overflow) => {
if (iGotIt) {
stack({
newKnowledge: 'Finally',
message: ':)'
})
}
}
f('test');
This also fails, because a string is not a function and can't be invoked like one.
Related
I have a question regarding curry function..
I know that if I have this simple curry function:
const greeting = (greet) => {
return (name) => {
return `${greet} ${name}`;
};
};
I can call greeting('Hello')('John') and it will return Hello John.
Is there a way to make it flexible say between 1 parameter and 2 parameters, ex: with
the above greeting function, is there a way for me to call greeting('Hello') and greeting('Hello')('John') and it will return Hello and Hello John respectively?
I know that I can do it with greeting('Hello')() and greeting('Hello')('John') but I was just trying to avoid breaking changes because I already have a greeting method and want to extend it using curry function, so I want it to also accept greeting('Hello') without the extra () at the end...
thanks
I can think of only one option that works by coercing the curried function into a string. This won't change the return value but it will allow you to get the result you want depending on context.
const greeting = greet => Object.defineProperties(
name => `${greet} ${name}`, // curried
{
toString: {
value: () => greet,
},
valueOf: {
value: () => greet
}
}
)
console.log(typeof greeting("Hello")) // function, not string
console.log(`${greeting("Hello")}`) // note the string context
console.log(`${greeting("Hello")("World")}`)
If you need the return value to actually toggle between a function and a string however, the answer is no.
In order for greeting("Hello")("John") to return a string, greeting("Hello") must return a function.
There is no way to tell within greeting() how the curried function is going to be called so you cannot detect whether or not to return a function or a string.
Think of it this way, greeting("Hello")("John") is just a short version of...
const fn = greeting("Hello")
// later or maybe never...
fn("John")
You simply don't know how, when or even if that curried function will be called.
Is there a way? Sure. But why? because won't that be "un-currying" it? And you will have to modify the function of-course.
You can always do something like this just get the output your asked for:
const greeting = (greet) => {
const split = greet.split(" ");
if(split.length > 1)
return `${split[0]} ${split[1]}`;
else return (name) => {
return `${greet} ${name}`;
};
};
If you use a helper function for currying, you can get a similar behavior automatically. For example, take the implementation at javascript.info/currying-partials
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function(...args2) {
return curried.apply(this, args.concat(args2));
}
}
};
}
You can define
const greeting = curry((greet, name) => `${greet} ${name}`)
and call
greeting("Hello", "John")
or
greeting("Hello")("John")
Hello I'm learning about Javascript Callback Function, but I don't know how to set a default value to callback function.
let mul = (num1,num2) =>{
return num1*num2;
}
let cal = (num1,num2,cb) =>{
console.log(`The Answer is ${cb(num1,num2)}`)
}
cal(3,2,mul);
Here the code I tried to set a default value to callback function.
let sum = (num1,num2) =>{
return num1+num2;
}
let mul = (num1 = 3,num2 = 2) =>{
return num1*num2;
}
let cal = (num1,num2,cb) =>{
console.log(`The Answer is ${cb(num1,num2)}`)
}
cal(mul);
Instead of cal(numberone,numbertwo,mul);. Can I only call a function like this cal(mul);.
Edit
let testmul = (num1 = 3,num2 = 2) =>{
let result = num1*num2;
console.log(`${result}`);
}
testmul();
This is what I would like to do. If I doesn't put a number in function. The function will have a default value. But this time I want to try it with a Callback function.
The answers to your question read more: https://nodejs.org/en/knowledge/javascript-conventions/how-to-create-default-parameters-for-functions/
You have to check if the last parameter is undefined and then manually fix all the other parameters before continuing in the code. This case is also valid for modern JavaScript(ES6/ES2015). The example shows you how to do that:
const example = function (param1, optParam, callback) {
if (callback === undefined) {
// only two parameters were passed, so the callback is actually in `optParam`
callback = optParam;
//give `optParam` a default value
optParam = "and a default parameter";
}
callback(param1, optParam);
}
example("This is a necessary parameter", console.log);
example("This is a necessary parameter", "and an optional parameter", console.log);
let DefaultCallback = (args) => {
... do stuff
}
then you can do like this:
function myFunc(param1, param2, callback = DefaultCallback){
return param1;
callback();
}
then if you don't provide a callback like myFunc(2) as you said, it will have the default values of the function defaultCallback and it works for other variables as well, if you want to define default function parameters
I have a question regarding ‘this’ in JavaScript higher-order-function's callback.
I've been exploring the following code - the goal is conversion of a function that accepts a callback into a function returning a promise.
Source: https://javascript.info/promisify
A function that accepts a callback:
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Script load error for ${src}`));
document.head.append(script);
}
Now, the author uses a higher-order-function that will accept the stated above function as a callback and do the promisification:
function promisify(f) {
return function (...args) {
return new Promise((resolve, reject) => {
function callback(err, result) {
if (err) {
return reject(err);
} else {
resolve(result);
}
}
args.push(callback);
f.call(this, ...args);
});
};
};
// usage:
let loadScriptPromise = promisify(loadScript);
loadScriptPromise('path/script.js').then(...);
The thing that I don't understand is:
Why do we call the f function in this way:
f.call(this, ...args); ?
What will ‘this’ be in this case?
Why can't we just call it like this: f(...args); ?
I know that in order to track down what a callback’s ‘this’ is pointing to, you need to inspect the higher order function enclosing it...
But I can't get why in this case do we have to state the callback’s ‘this’ explicitly?
Thank you for the help!
Why do we call the f function in this way: f.call(this, ...args); ?
What will ‘this’ be in this case? Why can't we just call it like this: f(...args); ?
Let me answer the What will ‘this’ be in this case? part first:
We don't know (in general) and that is why .call is used, but I will get to that.
promisify is supposed to "seamlessly" wrap an existing function. That means that calling either f or promisify(f) should return the same result.
The value of this depends on how a function is called. promisify can't know how the new wrapper function is going to be called, nor does it know whether the wrapped function uses this or not. Therefore it needs to assume that this is going to be significant and has to call the wrapped function in a way that sets this correctly.
The only way to call a function and explicitly set the this value is via .call or .apply. If the function was called as f(...args) then this inside f would either be the global object or undefined.
Here is a simpler wrapper function that demonstrates the issue:
function wrapWithThis(f) {
return function(...args) {
f.call(this, ...args);
}
}
function wrapWithoutThis(f) {
return function(...args) {
f(...args);
}
}
function wrapMe() {
console.log(this.foo);
}
const obj = {
foo: 42,
withThis: wrapWithThis(wrapMe),
withoutThis: wrapWithoutThis(wrapMe),
};
obj.withThis();
obj.withoutThis();
Having said all that, specific to your example, given that loadScript doesn't use this, it wouldn't make a difference if f.call(this, ...) or f(...) was used.
I'm trying to wrap a list of functions over a callback function. Each of the function in the list takes in the value of the callback and returns a modified value. When I try to do this in a straight forward way, it does recursion, and the stack eventually runs out of space, and throws an error.
I tried solving the problem by using a wrapper function that took in a function, wrapped it with another one, and then returned it, and that solved the problem.
Look at the subscribe function:
class Observable {
constructor() {
this._subscribers = [];
this._operators = [];
}
next(val) {
this._subscribers.forEach(subscriber => {
subscriber(val);
});
}
subscribe(callback) {
if (this._operators.length > 0) {
let ogCallback;
this._operators.forEach((operator, index) => {
ogCallback = callback;
/** ==== call stack full error =====
* callback = (val) => {
* ogCallback(operator(val));
* };
*/
// This works
callback = ((func) => {
const wrapper = (val) => {
func(operator(val));
};
return wrapper;
})(ogCallback);
});
this._operators = [];
}
this._subscribers.push(callback);
}
pipe(operator) {
this._operators.unshift(operator);
return this;
}
}
const observable = new Observable();
observable.pipe(val => val + 2).pipe(val => val * 2).subscribe(val => console.log(val));
observable.next(5);
Why does this happen? They both seem to be the same thing.
I suspect it's from the series of closures created by:
ogCallback = callback;
callback = (val) => {
ogCallback(_function(val));
}
ogCallback and callback are global. After the initial iteration, callback has the value:
(val) => ogCallback(_function(val))
ogCallback has a closure to the global ogCallback, so it's value is whatever it was given from the last iteration, as does callback, potentially causing circular references.
The second example breaks the closure by creating a local variable func in the assigned function expression that is passed the value of ogCallback using an immediately invoked function expression (IIFE).
Original second example
_functions.forEach((_function, index) => {
ogCallback = callback;
callback = ((func) => {
const wrapper = (val) => {
func(_function(val));
};
return wrapper;
})(ogCallback);
});
Can someone explain why the function below is not working (giving me an alert) when I try to call first(), however it works fine when I assign it to a new const?
const first = () => {
const greet = "Hi";
const second = () => {
alert("greet");
}
return second;
}
first() // does not work
const newFunc = first();
newFunc(); // works
Is this something specific to ES6 or am I missing something?
Thank you everyone! I had a brain fart, I kept focusing on the new syntax thinking that I made a mistake or it works in a different way, but I was never calling the second function returned by the first one. I changed it to:
const first = () => {
const greet = "Hi";
const second = () => {
alert("greet");
}
return second;
}
first()
It works now!
first() works just fine and returns the second() function, but I don't think you expected this. And your try to copy it used () and thus called it, returning the second function. After that newFunc contains second and calling it gives you the intended result.
first() only returns a function object - therefor another set of () is needed to actually call that returned function.
It doesn't need assignment to const newFunc though - first()(); would get you your alert as well.
This technique of having a function return another function, or an object that exposes several functions that can then in turn be called, is know as Revealing Module Pattern.
You're returning "second" as a function, but you never execute, you have 2 options, return "second()" or execute after receive it.
const first = () => {
const greet = "Hi";
const second = () => {
alert("greet");
}
return second;
}
first()(); // does work
//Alternative
const secondTime = () => {
const greet = "Hi";
const second = () => {
alert("greet");
}
return second();
}
secondTime();
Hope this works.