Ignore Calling Argument - javascript

Is it possible do not include an argument conditionally when calling a function?
Exemple
Here is a snippet of what behavior I am wanting:
const a=1;
const b="spam";
console.log( a, b!="spam"?b:undefined ); // I would like to ignore b when b=="spam"
// expected output: "1"
// actual output: "1 undefined"
Testings
Here is a snippet representing a logging of every value I have tested so far:
Value
const a="a";
const b=0;
const c=NaN;
const d=null;
const e=undefined;
const f=void 0;
const g="g";
console.log(a,b,c,d,e,f,g);
// expected output: a 0 NaN null g
// actual output: a 0 NaN null undefined undefined g
Filter
const variable = null;
let test = [variable].filter(f => f != null).join();
console.log("start");
console.log(); // no output
console.log(test); // output: "" (type: string)
console.log(typeof test); // output: "string"
console.log(); // no output
console.log("end");
Filter & Apply
const variable=null;
let test = [variable].filter(f => f != variable);
console.log("start");
console.log(test); // output: "(0) []"
console.log.apply(console, test); // no output
console.log.apply(console, null); // no output
console.log("end");
Workaround
That:
const a=1;
const b="spam"
b!="spam"?console.log(a,b):console.log(a);
works, but it is not ignoring an argument at call, it rather test the variable before to then not include it as an argument

Build an array, filter it of unnecessary values, then use the spread syntax ..., like this
const a = "a";
const b = 0;
const c = NaN;
const d = null;
const e = undefined;
const f = void 0;
const g = "g";
console.log(...[a, b, c, d, e, f, g].filter((x) => x !== undefined));
If you want, you can declare as well your console.logDefined function, like this:
console.logDefined = function () {
console.log(...Array.from(arguments).filter((x) => x !== undefined));
};
const [a, b, c, d, e, f, g] = ["a", 0, NaN, null, undefined, void 0, "g"];
console.log( "console.log array >>", a, b, c, d, e, f, g);
console.logDefined("console.logDefined array >>", a, b, c, d, e, f, g);

Related

Writing unit test case for nested function in javascript using mocha,sinon,chai

I want to write unit test case for fn1() following code:
function add(a, b){
const q = 5
console.log(a)
console.log(b)
const c = a + b
console.log(c)
console.log('1')
return c
}
function fn1(){
let a = 5;
let b = 6;
let c = obj.add(a, b);
console.log(a)
console.log(b)
console.log(c)
console.log('1')
return c;
}
And I want to pass different arguments to add(a, b) in fn1(). How can I do that using mocha, sinon, chai?
You can use sinon stub, stub the add method and call wrappedMethod, which is a reference to original method; in order to force pass different arguments to add method.
But you need to structurize your code a little bit.
Here is the simple example to show you how to do it.
I create method add and method fn1 inside check object on file check.js
// File: check.js
const check = {
add: (a, b) => {
const q = 5
console.log('add a:', a)
console.log('add b:', b)
const c = a + b
console.log('add c:', c)
console.log('add called');
return c
},
fn1: () => {
let a = 5;
let b = 6;
let c = check.add(a, b);
console.log('fn1 a:', a);
console.log('fn1 b:', b);
console.log('fn1 c:', c);
console.log('fn1 called');
return c;
},
};
module.exports = check;
And I create simple test file: check.spec.js
// File: check.spec.js
const sinon = require('sinon');
const check = require('./check');
describe('check', () => {
it('pass different argument to add()', () => {
sinon.stub(check, 'add').callsFake(
function () {
console.log('stub add:', arguments);
// Change the arguments here:
arguments['0'] = 7;
// Call write method with modified arguments.
return check.add.wrappedMethod.apply(this, arguments);
}
);
check.fn1();
});
});
I change the first argument a to 7. Here is the result when I run it at terminal:
$ npx mocha check.spec.js
check
stub add: [Arguments] { '0': 5, '1': 6 }
add a: 7
add b: 6
add c: 13
add called
fn1 a: 5
fn1 b: 6
fn1 c: 13
fn1 called
✓ pass different argument to add()
1 passing (4ms)

ES6 destructuring not returning correct result

I an trying to destructure two object with the same property names but only the names of the first set are observed.
let a, b,
({ a,b } = myObject1);
({ a,b } = myObject2);
ie; only the values for myObject1 are in the console.log()
Does anyone know how to destructure properties of the same name from different objects ? I do not want to manually assign each variable.
I had tried
let a, b,
({ a,b } = myObject1);
({ a : test1,b: test2 } = myObject2)
console.log(test1)
and
let a, b,
{ a,b } = myObject1;
{ a : test1,b: test2 } = myObject2
console.log(test1)
But test1 is undefined
let { a: a1, b: b1 } = myObject1;
let { a: a2, b: b2 } = myObject2;
Will create variables a1, b1, a2, b2 from your 2 objects.
Assign name to variables.
let a, b,
({ a,b } = myObject1);
({ a: A,b:B } = myObject2);
If you have more objects with the same structure, you could take a function which returns an array of wanted properties.
const getProps = ({ a, b }) => [a, b];
let [a, b] = getProps(myObject1),
[c, d] = getProps(myObject2);

Strict equal inside of array

I want to check that two arrays contain the same elements (not deep equals) in the same order.
var a = { id: 1 }
var b = { id: 2 }
var c = { id: 3 }
var arr = [a, b, c]
expect(arr).to.______([a, b, c]) // true
expect(arr).to.______([a, c, b]) // false: different order
expect(arr).to.______([a, b]) // false: missing element
expect(arr).to.______([a, b, c, { id: 4 }]) // false: extra element
expect(arr).to.______([a, b, { id: 3 }]) // false: different object reference
Of course I can write
assert.strictEqual(arr.length, expected.length, "length");
for (let q = 0; q < arr.length; ++q) assert.strictEqual(arr[q], expected[q], `[${q}]`);
But I think there should be some method for that already.
You could use .ordered in conjunction with .members, like this:
By default, members are compared using strict (===) equality. Add .deep earlier in the chain to use deep equality instead.
const expect = chai.expect;
const a = 1;
const b = 2;
const c = 3;
const input = [a, b, c];
expect(input).to.have.ordered.members([a, b, c]);
expect(input).to.not.have.ordered.members([b, a, c]);
expect(input).to.not.have.ordered.members([a, c, b]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.2.0/chai.min.js"></script>

Save reference to a function with parameters in JavaScript

I am calling a function at several places within my app. This function takes several parameters whose values might change. To avoid re-typing, I want to save a reference to this function so that I can simply call this referred function everywhere. Here is the simplified code:
const func1 = (a,b,c) => a + b + c;
let a = 1, b = 2, c = 3;
const func2 = func1.bind(this, a, b, c);
func2();
//prints 6
c = 6;
func2();
//still prints 6!
How can I ge func1 to be executed with updated values of a, b and c by calling func2?
Use arrow function:
const func1 = (a,b,c) => a + b + c;
let a = 1, b = 2, c = 3;
const func2 = () => func1(a, b, c);
console.log(func2());
c = 6;
console.log(func2());
You can bind the function to an array of [a, b, c] instead, and then change the property at index 2:
const func1 = (a,b,c) => a + b + c;
const params = [1, 2, 3];
const func2 = () => func1(...params);
func2();
params[2] = 6;
func2();
If you only change c, you could consider binding the function to a and b, and then passing the changing c:
const func1 = (a,b,c) => a + b + c;
const params = [1, 2];
const func2 = (c) => func1(...params, c);
func2(3);
func2(6);
If you want to use params from scope where you declare your function, just skip those params in function signature
const f = () => a + b + c;
let a = 1, b = 2, c = 3;
console.log(f());
c = 6;
console.log(f());
Instead of this const func2 = func1.bind(this, a, b, c);
You can use this function(arrow): const func2 = () => func1(a, b, c);

Passing a specific pre-defined parameter to a function

Let it be so :
let something = (a , b , c = 0 , d = 0 , e = 0) =>
{console.log(`a is ${a}; b is ${b};c is ${c};d is ${d};e is ${e}`)};`
If I give more then two params to a function, it takes them as respectively.
What if I want to pass the value to "e" variable and skip others, that are predefined?
You can make the params an object.There are two benefits to it, first, you don't have to worry about the order and you won't have to pass a value to c or d.
let something = ({a , b , c = 0 , d = 0 , e = 0}) => {
return `a is ${a}; b is ${b};c is ${c};d is ${d};e is ${e}`;
}
console.log(something({a: 12 , b: 13, e: 51})); //"a is 12; b is 13;c is 0;d is 0;e is 51"
Just pass undefined:
let something = (a, b, c = 0, d = 0, e = 0) => {
console.log(`a is ${a}; b is ${b}; c is ${c}; d is ${d}; e is ${e}`);
};
something(1, 2, undefined, undefined, 3);
You can also wrap the optional parameters in a single argument which will be destructured:
let something = (a, b, {c=0, d=0, e=0} = {}) => {
console.log(`a is ${a}; b is ${b}; c is ${c}; d is ${d}; e is ${e}`);
};
something(1, 2);
something(1, 2, {c: 3});
something(1, 2, {e: 3});

Categories