How to resolve no-param-reassign error in a function - javascript

In a Node/JS function, I'm getting ESLint no-param-reassign the code is for update a candidate as follow
update(candidate) {
const { id } = candidate;
if (!id) {
throw new UserInputError('id is mandatory');
}
return this.tx(tableName)
.returning(Object.values(columnsByProperties))
.where('id', id)
.update(prepareCandidate(candidate))
.reduce((_, b) => camelcaseKeys(b), null)
.then(x => {
if (!x) {
throw new UserInputError(`Candidate "id" with ${id} is not found`);
}
x.preferredContact = x.preferredContactHours;
return x;
});
}
The error specifically is here Assignment to property of function parameter 'x'
.then(x => {
if (!x) {
throw new UserInputError(`Candidate "id" with ${id} is not found`);
}
x.preferredContact = x.preferredContactHours;
return x;
});

You can replace:
x.preferredContact = x.preferredContactHours;
return x;
With this:
return { ...x, preferredContact: x.preferredContactHours };
This way you return a new object instead of modifying the function's parameter.
Now, elaborating a bit. As the rule's documentation says:
Assignment to variables declared as function parameters can be misleading and lead to confusing behavior, as modifying function parameters will also mutate the arguments object.
"Confusing behavior" is to be understood as, for example, odd side effects. I remember wreaking havoc in an app because inside a function, I mutated an array that was passed as a parameter. The array was also mutated in the calling code which was bad. That's the kind of thing ESLint helps prevent!

Related

How do functions defined with => get called in Angular?

From here: https://angular.io/tutorial/toh-pt4 - hero.component.ts
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
I have understood that this heroes => this.heroes = heroes translates to as follows:
f( heroes )
{
return this.heroes = heroes;
}
Is return implied here?
I want to understand where from does this inner function get called. Who's calling it?
In the example code you provided,to return a list of heros, we have to write it like
getHeroes(): Hero[] {
this.heroService.getHeroes()
.subscribe(heroes => ({heroes : heroes}));
}
Above arrow function will translate to
f( heroes )
{
return this.heroes = heroes;
}
Otherwise, the code you provided, its just making an assignment to this.heros variable, so return statement does not apply, and the arrow function translate to
f( heroes )
{
this.heroes = heroes;
}
Further explanation of Arrow function
Arrow functions, like function expressions, can be used to return an object literal expression. The only caveat is that the body needs to be wrapped in parentheses, in order to distinguish between a block and an object (both of which use curly brackets).
Example
//ES5
var setNameIdsEs5 = function setNameIds(id, name) {
return {
id: id,
name: name
};
};
// ES6
var setNameIdsEs6 = (id, name) => ({ id: id, name: name });
console.log(setNameIdsEs6 (4, "Kyle")); // Object {id: 4, name: "Kyle"}
For a regular function, if the ‘this’ keyword were inside an object’s method (a function that belongs to an object), it would refer to the object. While in an arrow function, ‘this’, always references the owner of the function it is in. Adding a console.log(this) before the return in the arrow function returns a Window object.
Example
// ES5
const brunch = {
food: 'Dim sum',
beverage: 'Jasmine tea',
order: function() {
return `I'll have the ${this.food} with ${this.beverage} please.`
}
}
brunch.order(); //"I'll have the Dim sum with Jasmine tea please."
// ES6
const brunch = {
food: 'Dim sum',
beverage: 'Jasmine tea',
order: () => {
return `I'll have the ${this.food} with ${this.beverage} please.`
}
}
brunch.order(); //"I'll have the undefined with undefined please."
In the following arrow function heroes => this.heroes = heroes
Yes, return is implied, this may or may not be a problem depending on the rest of your code. I'm assuming in your case, you're not looking to return the assignment, you just want the assignment to happen.
So all you have to do is wrap the result in braces like so heroes => {this.heroes = heroes}, now nothing is returned.
As for your second question, who calls the inner arrow function: From the looks of your code, this.heroService.getHeroes() returns an observable. In your code you have "subscribed" to the observable. The easy way to think about is that the observable is telling your subscription to run the arrow function.
Basically, you are observing the observable. The observable needs time to think about it's response which is why you need to subscribe to it. When it is ready it will tell you it's response, and your arrow function inside the subscription is your response to the observable response. This is a very non-technical description to give you some intuition.
You should research observables/async functions to get a clear understanding.
this.heroService.getHeroes() returns a subscription object. In order to subscribe to it we should use .subscribe(heroes => this.heroes = heroes);.
subscribe maps the subscription object and extracts the data from the object and puts it in this.heroes, the first param inside the subscribe.
Then with the => operator we start writing actions like affectation, displaying, or anything to do, you can do anything after =>
in order to write more than one action you should use the braces like this:
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => { console.log('ur data from the observable',heroes);
this.heroes = heroes
});
}

ES6 Proxies: trapping undefined function executions

Let's say I have the following object with two functions as properties:
const foo = {
f1: () => {...},
f2: () => {...},
}
I would like to perform a specific action (for example, throw a custom error) when someone tries to execute a function that doesn't exist on the foo object.
I've tried using a get proxy, but that throws an error even when I'm not trying to execute f3, such as in the following code:
if (foo.f3) {...}
So how can I write my proxy in such a way that foo.f3 returns undefined as it usually would, but foo.f3() does throw an error?
Here's a partial solution, inspired by Unmiss.
const handler = {
get: function(obj, prop) {
if (prop in obj) {
return obj[prop];
} else {
return () => {
throw new Error(`Foo.${prop} is undefined`);
}
}
}
};
The problem with this is that while it accomplishes the goal of only throwing an error when you actually try to execute Foo.f3(), since Foo.f3 is now equal to that anonymous function is doesn't return undefined anymore, meaning that (as far as I can tell) if (Foo.f3) {...} will always return true.
Edit: as #paulpro points out:
You absolutely cannot do that. foo.f3 is either undefined or some
callable with custom logic; it cannot be both.
The best we could do is trap f3 in foo statements using the has trap, but this would mean if (f3 in foo) and if (foo.f3) would now have different results, which seems like a big red flag.
Is this what your asking for?
https://jsfiddle.net/MasterJames/bhesz1p7/23/
[obviously you need to F12 your dev tools to see the console output or change as desired]
Only real difference is to return undefined after throwing. It's as if the function executed without doing anything since it doesn't exist.
I'm sure there's a different solution based on the actual use case, but I like the idea/question. Keeps things more stable etc.
let foo = new Proxy(
{
f1: function (val) {
console.log(' F1 value:' + val);
return 'called OKAY with', val;
}
},
{
get: function(obj, prop) {
console.log("obj:", obj, " prop:", prop);
if (prop in obj) {
console.log("Found:", prop);
return obj[prop];
}
else {
console.log("Did NOT find:", prop);
throw new Error(`Foo.${prop} is undefined not called returning undefined`);
return undefined;
}
}
});
console.log("\nFoo Tester started");
console.log(' Does F1 exists', foo.f1 !== undefined);
console.log(' called F1 result:', foo.f1('passed') );
try {
console.log(' Does F2 exists', foo.f2 !== undefined);
console.log(' called F2 result:', foo.f2('passed') );
}
catch (err) {
console.log(' Error calling F2:', err );
}
console.log("Foo Tester finished");
Not sure you want to try-catch or not that's also up to you so in the end checking if it's real and a function is the same difference depending on how your going to handle the error.
if (foo.f2 && foo.f2.constructor === Function && foo.f2()) console.log("okay!");
Again you call build a safeCall wrapper more like this or something in between?
possible calling foo's 'customThrow' if it exists or what-have-you, so many possibilities with JS.
Okay so it took me sometime but I have a solution now.
I was not fully understanding your question, which I reformulated as a question within the question for myself to understand the issue better as it is complicated.
Basically you want to know if it's being called or not so the function you need in the proxies 'get' is 'isCalling'.
The solution is not clean in JS Fiddle because it's messy there at least for this kind of problem's solution.
Basically the solution is a sentence is, "you have to use an error to get a stack trace then retrace the source code that is calling and look for a right bracket or not.", to determine how it's being called and return whatever you want then).
[Please note this depends on your code and how you call it so you would adjust as needed.]
Since you have to find the location in the source code that's being called from it's way better if there is no inline script tag as is the case in this JSFiddle example. I'm using outerHTML to get the source, when arguments.callee.caller.toString() is better from an actual JS file. You'll also not the location from the stacktrace is skewed by odd behavior here, so with a normal JS file the code would align properly using other solutions are recommended. If anyone knows how to get a clean source that aligns with the error trace every time with script-tag blocks etc. Also note coming but not existing yet are things like Error.lineNumber.
[Please don't bother with the version history it was a nightmare to sort this one out. And again you would be better to use other npm packages to do the source code from stack trace parts.]
Anyway the example I believe achieves what you want but in principle demonstrates what you'd need to do better in a given real (no Fiddle) situation. I'm pretty sure doing this is not a great solution in production either and I've not tested the timing (performance speed) but if it really was that important to your cause (and no other better solution which I doubt) then it will work.
Originally I discovered this technique when I was doing something experimental, and instead of just sending another argument I was checking to see what was actually calling it and adjusting the functions action depending.
Usages are extensive when you start to think more about it as I did last year when I first did something like this. Examples are as an extra function execution Security Check, Realtime mystery-bug Debug Solution, a way to execute the function differently without passing more arguments, runaway recursive loops (how long is the stack), to name a few.
https://jsfiddle.net/MasterJames/bhesz1p7/90/
let foo = new Proxy(
{
f1: function (val) {
console.log(' F1 value:' + val);
return 'called OKAY with', val;
}
},
{
isCalling: function() {
let stk = new Error();
let sFrms = this.stkFrms(stk.stack);
console.log("stkFrms:", sFrms);
//BETTER From real pure JS Source
//let srcCod = arguments.callee.caller.toString()
let srcCod = document.getElementsByTagName('html')[0].outerHTML.split("\n");
let cItm = sFrms[(sFrms.length - 1)];
if(cItm !== undefined) {
let cRow = (parseInt(cItm[1]) - 3);
let cCol = (parseInt(cItm[2]) + 1);
let cLine = srcCod[cRow];
let cCod = cLine.substr(cCol, 1);
if(cCod === '(') return true;
}
return false;
},
stkFrms: function (stk) {
let frmRegex1 = /^.*at.*\(.*\:([0-9]*)\:([0-9]*)\)$/;
let frmRegex2 = new RegExp(frmRegex1.source, 'gm');
let res = [], prc, mtch, frms = stk.match(frmRegex2);
for(mtch of frms) {
prc = frmRegex1.exec(mtch);
res.push(prc);
}
return res;
},
get: function(obj, prop) {
if (prop in obj) {
console.log("Found:", prop);
return obj[prop];
}
else {
if(this.isCalling() === false) {
console.log("Did NOT find:", prop);
return undefined;
}
else {
console.log("Did NOT find return custom throw function:", prop);
return function() {throw new Error(`Foo.${prop} is undefined`);}
}
}
}
});
console.log("foo.f1:", foo.f1);
console.log("foo.f1('passed'):", foo.f1('passed'));
console.log("foo.f2:", foo.f2);
try {
console.log("foo.f2('passed2'):", foo.f2('passed2'));
}
catch(err) {
console.log("foo.f2('passed2') FAILED:", err);
}
console.log("'f2' in foo:", 'f2' in foo);
Okay so a verbal run through:
You want to check foo.f2 is undefined so it returns that because it's not being called.
If you do call it (f2) without simply checking first and erroring as needed, and you don't want to try-catch to throw your custom error based on the function name, you want it to return an actual function that will throw a custom error.
You also want to use 'in' to see that it's undefined, which is the same as false (maybe hack it further to send false instead of undefined via something like isCallingFromIn too.
Did I miss anything? Is this not what you all thought was impossible?

Why would you ever call .call() on Observable functions?

I am a relative beginner in Angular, and I am struggling to understand some source I am reading from the ng-bootstrap project. The source code can be found here.
I am very confused by the code in ngOnInit:
ngOnInit(): void {
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
const results$ = letProto.call(inputValues$, this.ngbTypeahead);
const processedResults$ = _do.call(results$, () => {
if (!this.editable) {
this._onChange(undefined);
}
});
const userInput$ = switchMap.call(this._resubscribeTypeahead, () => processedResults$);
this._subscription = this._subscribeToUserInput(userInput$);
}
What is the point of calling .call(...) on these Observable functions? What kind of behaviour is this trying to achieve? Is this a normal pattern?
I've done a lot of reading/watching about Observables (no pun intended) as part of my Angular education but I have never come across anything like this. Any explanation would be appreciated
My personal opinion is that they were using this for RxJS prior 5.5 which introduced lettable operators. The same style is used internally by Angular. For example: https://github.com/angular/angular/blob/master/packages/router/src/router_preloader.ts#L91.
The reason for this is that by default they would have to patch the Observable class with rxjs/add/operators/XXX. The disadvantage of this is that some 3rd party library is modifying a global object that might unexpectedly cause problems somewhere else in your app. See https://github.com/ReactiveX/rxjs/blob/master/doc/lettable-operators.md#why.
You can see at the beginning of the file that they import each operator separately https://github.com/ng-bootstrap/ng-bootstrap/blob/master/src/typeahead/typeahead.ts#L22-L25.
So by using .call() they can use any operator and still avoid patching the Observable class.
To understand it, first you can have a look at the predefined JavaScript function method "call":
var person = {
firstName:"John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
var myObject = {
firstName:"Mary",
lastName: "Doe",
}
person.fullName.call(myObject); // Will return "Mary Doe"
The reason of calling "call" is to invoke a function in object "person" and pass the context to it "myObject".
Similarly, the reason of this calling "call" below:
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
is providing the context "this._valueChanges", but also provide the function to be called base on that context, that is the second parameter, the anonymous function
value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
}
In the example that you're using:
this._valueChanges is the Input Event Observerable
The _do.call is for doing some side affects whenever the event input happens, then it returns a mirrored Observable of the source Observable (the event observable)
UPDATED
Example code: https://plnkr.co/edit/dJNRNI?p=preview
About the do calling:
You can call it on an Observable like this:
const source = Rx.Observable.of(1,2,3,4,5);
const example = source
.do(val => console.log(`BEFORE MAP: ${val}`))
.map(val => val + 10)
.do(val => console.log(`AFTER MAP: ${val}`));
const subscribe = example.subscribe(val => console.log(val));
In this case you don't have to pass the first parameter as the context "Observable".
But when you call it from its own place like you said, you need to pass the first parameter as the "Observable" that you want to call on. That's the different.
as #Fan Cheung mentioned, if you don't want to call it from its own place, you can do it like:
const inputValues$=this._valueChanges.do(value=>{
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
})
I suppose
const inputValues$ = _do.call(this._valueChanges, value => {
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
});
is equivalent to
const inputValues$=this._valueChanges.do(value=>{
this._userInput = value;
if (this.editable) {
this._onChange(value);
}
})
In my opinion it's not an usual pattern(I think it is the same pattern but written in different fashion) for working with observable. _do() in the code is being used as standalone function take a callback as argument and required to be binded to the scope of the source Observable
https://github.com/ReactiveX/rxjs/blob/master/src/operator/do.ts

reduce function with empty object is not working

I'm trying to create object from form elements. For some reason, it is throwing the error.
let allInputs = [...formData];
allInputs.pop(); //Remove submit button
return allInputs.reduce((userObj, data) => userObj[`${data.name}`] = data.value, {});
Error
userModel.js:17 Uncaught TypeError: Cannot create property 'last_name' on string ''
You need to return accumulator or in your case userObj in each iteration of reduce so your code should look like this.
allInputs.reduce((userObj, data) => (userObj[`${data.name}`] = data.value, userObj), {});
The problem is what you're returning the second time your reducer is called, not what you start with.
You are returning an assignment but should return an object.
(userObj, data) => userObj[`${data.name}`] = data.value // <-- this returns the result of the assignment
Something like this should work:
allInputs.reduce(
(userObj, data) => Object.assign(userObj, {
[data.name]: data.value
}),
{}
);
Note: as mentioned by Vic in the comment, no need for string interpolation, i.e. ${data.name} -> just data.name is enough.

inside Array.push without a function call

I want to perform more logic before writing an element to an array:
tempDatensatz.push( () => {
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
});
Getting the value from that array will be achieved like this:
tempDatensatz[0]()
But I want the same logic in it without having a function to call. I need a normal array, where I get a value like this:
tempDatensatz[0]
What can I do instead?
Updated
I published my project to gitHub, you can take a look if you need a better understanding :)
https://github.com/te2020/GoEuro/blob/master/GoEuro/Views/Home/Index.cshtml
Use an immediately invoked function instead of just a function:
tempDatensatz.push( (function(){
var current = window.dataForDataTable[i].outbounds[key].updatedAt;
if (current) {
return current.toString();
} else {
return "".toString();
}
})());
The function will be executed immediatly after it definition, returning the result. So push won't push a reference to that function but instead it will push it returned value (the result).
You can write a proxy as follows:
function makeProxy(array) {
return new Proxy(array, {
get(target, property) {
return !isNaN(property) ? target[property]() : target[property];
}
});
}
const tempDatensatz = [];
const useThisOne = makeProxy(tempDatensatz);
useThisOne.push(() => alert("Hi, Jane!"));
useThisOne[0];
Pushing/writing to the array will work as expected, but retrieving its elements will go through the get handler, which will execute the function.
You could just use an expression, like:
tempDatensatz.push(
(window.dataForDataTable[i].outbounds[key].updatedAt || '').toString();
);
For more complex expressions you can often use the ternary operator. For the above that would look like this:
tempDatensatz.push(
window.dataForDataTable[i].outbounds[key].updatedAt
? window.dataForDataTable[i].outbounds[key].updatedAt.toString()
: ''
);
Your code
When looking at the github code you linked to, you can do all that pushing with this "oneliner":
var tempDatensatz =
['companyId', 'mode', 'duration', 'outboundId', 'journeyId', 'departureTime',
'arrivalTime', 'stops', 'price', 'updatedAt', 'segments']
.map( prop => (window.dataForDataTable[i].outbounds[key][prop] || '').toString() );

Categories