how to handle this default parameter in javascript? [duplicate] - javascript

This question already has answers here:
Skipping optional function parameters in JavaScript
(4 answers)
Closed 3 years ago.
I have a function which has two default parameters and one regular
parameter.
var Fields = function ($content, result = failedObject, job = true)
{
...
}
When I call Fields($content,job), job here could be true or false, the result parameter takes in the job value rather than the third parameter. Works good in the case if Fields($content,result).
Any good way to tackle this situation.

you would call Fields($content, undefined, job) to use the default value for the parameter result

if I understood your question correctly, javascript does not support named parameters natively, so you can call by Fields($content, undefined, job)
or using an object as parameter for your function instead of 3 params.

You could use a destructured argument :
var Fields = function ($content, { result = failedObject, job = true } = { }) {
...
}
Then, when you call the function :
const data = { result: anotherObject, job = false };
Fields('toto', data);
Or, in your specific case :
const data = { job = false };
Fields('toto', data); // result still is a failedObject

Pass empty/undefined/null:
Fields($content, , job);

You must switch the order(like below), or using an array and treat inside function.
var Fields = function ($content, job = true, result = failedObject, )
{
}

Related

Is it possible to provide default parameters with rest operator

I was learning from an ES6 essential course and trying default parameters and rest operator for functions.
I have defined a function sayHi as below with default parameters and then rest operator which does not gives the desired output.
const sayHi = (greetings, ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi('Hi', 'Ahsan', 'Awais', 'Haseeb');
The above snippet works as desired. but when I tried to set a default parameter value for greetings variable it works but gives unwanted result i.e. value 'Ahsan' is taken by the greetings variable.
const sayHi = (greetings = ' Hi', ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi('Ahsan', 'Awais', 'Haseeb');
Is there a way I can set default parameters in function like above before rest operator?
You can't, no. The rest parameter only picks up the "rest" of the parameters not consumed by any previous formal parameters, so greeting will always receive the first argument's value.
Separately, since both the names and the greeting have the same type, you can't provide a default at all if you want to accept the names that way.
A couple of options for you:
A curried function
You could have a function that accepts the greeting and returns a function that uses it with whatever you pass it:
const greet = (greeting = "Hi") => (...names) => {
for (const name of names) {
console.log(`${greeting} ${name}`);
}
};
greet()("Ahsan", "Awais", "Haseeb");
greet("Hello")("Ahsan", "Awais", "Haseeb");
Note how we called that:
greet()("Ahsan", "Awais", "Haseeb");
greet() creates the function using the default greeting. Then we call that function by using ("Ahsan", "Awais", "Haseeb") on it. greet("Hello") creates a function that uses the greeting "Hello" (and then we call it).
(I also took the liberty of using for..of rather than forEach, but it's a matter of style.)
Take names as an array
Another option is to accept the names as an array. That way, we can tell inside the function whether we got a greeting or not:
const greet = (greeting, names) => {
if (Array.isArray(greeting)) {
names = greeting;
greeting = "Hi";
}
for (const name of names) {
console.log(`${greeting} ${name}`);
}
};
greet(["Ahsan", "Awais", "Haseeb"]);
greet("Hello", ["Ahsan", "Awais", "Haseeb"]);
you just have to pass undefined in the 1st parameter to skip optional arg
think of it like this greetings = typeof greetings != 'undefined' ? greetings : "hi" which means that check the value of greetings and if it's undefined (not provided) use the default value
edit: here is the code snippet
const sayHi = (greetings = ' Hi', ...names) => {
names.forEach(item => {
console.log(`${greetings} ${item}`);
});
}
sayHi(undefined, 'Ahsan', 'Awais', 'Haseeb');

javascript array value as variable name , how I get them from function

I'm using array value as variable and then call the function N method, how I get them in function N.
I really want to simulate the Javascript array method, I don't want to use parameters to achieve it. For example,
var p1 = [1,2,3,4,5]; p1.push(6);
function _Array() {
this._this = this;
}
_Array.prototype.show = function () {
this._this.forEach(function(item){alert(item);}) //how to print 1,2,3,4,5
};
var p1 = [1,2,3,4,5];
p1 = new _Array();
//p1._Array.call(p1); //not work
// new _Array().show.call(p1); //not work
// p1.show(); //not work
You have to store that in the instance
function N(arr) {
this._this = arr
}
N.prototype.say = function () {
this._this.forEach(function (item) {
console.log(item)
})
}
p1 = new N([1, 2, 3, 4, 5])
p1.say()
If you are insistent on wanting to write a method that takes the array by reference, you can modify the array prototype like so:
Array.prototype.show = function() {
this.forEach(item => alert(item));
}
However, it is a VERY BAD IDEA to modify the built in object prototypes, as this can cause conflicts with external libraries implementing their own "show" function that is being used differently, or cause incompatibilities with future versions of JS that implements this method.
It would be far more prudent in most situations to pass the array as a parameter, unless you have a very specific reason why you're not doing so. In that case, you should at least prefix the method with some sort of project identifier to minimize the chances of conflicts occurring.

calling a smart contract functons as a a string in javascript web3

Here is my question: Instead of calling a smart contract function like this
//assuming the name of the contract function is called "balanceOf"
contract.methods.balanceOf("0x", "0x").call(err, balance) => {
console.log({err, balance});
})
i want to know if it is possible to call like this:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods.funcName(parameter).call(err, balance) => {
console.log({err, balance}];
})
Thank You.
The objects in javascript can be accessed like an array by using the keys as indexes. So in your case it would be:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods[funcName]("0x", "0x").call(err, balance) => {
console.log({err, balance}];
})
But the way you passing the parameter is not going to work like that. You are just passing a string as a parameter. Think of it like passing parameters to any other function.

How do you (best) access 'this' in an object method passed as callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I'm writing a simple word game to practice my javascript (I'm new to it) using the NPM package prompt (https://www.npmjs.com/package/prompt) to query the user when I need a response.
Since I come from an OOP background (in other languages) I've been experimenting with encapsulating different functionalities in different objects. So I have all the prompt related code in one object, like this
function Prompter() {
this.getUserName = function (callback) {
var schema = {
properties: {
name: {
description: "Tu nombre por favor:",
pattern: /^[ñÑa-zA-Z\s\-]+$/,
message: 'Solo letras, por favor',
required: true
}
}
};
prompt.get(schema, callback);
};
}
and game logic in another object like this (this is the relevant part of the code)
function Game() {
this.qGenerator = null;
this.prompter = null;
this.user = "";
this.doNextRound = function () {
//// omitted for brevity
};
this.init = function () {
this.qGenerator = new QuestionGenerator();
this.prompter = new Prompter();
};
this.startGame = function () {
this.prompter.getUserName(this.storeUserName);
};
this.storeUserName = function (err, result) {
if (err) {
this.handleErr(err);
return;
}
this.user = result.name;
this.doNextRound();
};
}
and I start the game like this
const game = new Game();
game.init();
game.startGame();
The problem I have is that in the Game method storeUserName, which I've passed as a callback to prompt, I have no access to the Game object through this, and thus, when I call
this.doNextRound
inside of storeUserNameI get
TypeError: this.doNextRound is not a function
I understand why, as this refers to Node inside the callback. But I don't know how to keep a reference to the correct this inside the method I'm passing as callback. I understand how to do it in more 'vanilla' Javascript -- using that = this, or apply,etc, but I'm not sure what the best way to handle this inside Node callbacks is when you're passing another object's methods. Any advice much appreciated.
Use Function.prototype.bind:
this.prompter.getUserName(this.storeUserName.bind(this));
or an arrow function:
this.prompter.getUserName( _ => this.storeUserName() );
Either of those will work.

How to pass a parameter to a function that is passed to another function as string?

I have the following piece of code :
accountSelector.executeInParallel('processAccounts', 'postProcess');
function processAccounts() {
return JSON.stringify(syncMasterLists());
}
And instead of having this, I want to be able to pass a value to the processAccounts accounts function.
For the purpose I changed the code so it's looking like this now :
accountSelector.executeInParallel('processAccounts("DE")', 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Unfortunately, after introducing the change I started getting the following error :
Cannot find function processAccounts("DE").
I cannot understand am I doing this wrong(and if yes then what is wrong) or it's just something that can't be done.
I cannot understand am I doing this wrong(and if yes then what is
wrong) or it's just something that can't be done.
accountSelector.executeInParallel takes the function name as parameter and execute the same, processAccounts("DE") is not a valid function name or the name of the function that exists.
As per documentation, there is a way to pass optionalInput parameter
The input, if specified by optionalInput, will be passed into the
function specified by functionName
accountSelector.executeInParallel(functionName, optionalCallbackFunctionName, optionalInput)
In your case, it will be
accountSelector.executeInParallel('processAccounts', 'postProcess', 'DE' );
Why don't you call the function first and replace the result in the 'executeInParallel' method as follows:
var res = processAccounts("DE");
accountSelector.executeInParallel(res, 'postProcess');
function processAccounts(arg) {
return JSON.stringify(syncMasterLists());
}
Some closure can probably solve your problem, depends on how accountSelector.executeInParallel is implemented
const accountSelector = {
executeInParallel(pre, post) {
let result = eval(pre)()
eval(post)(result)
}
}
accountSelector.executeInParallel(processAccountsWithArg('Foo'), 'postProcess');
function processAccount(arg) {
console.log('processAccount', arg)
return JSON.stringify({
key: 'value'
});
}
function processAccountsWithArg(arg) {
return function() {
return processAccount(arg)
}
}
function postProcess(result) {
console.log('postProcess', result)
}

Categories