ESLint error: 'value' is never reassigned use 'const' instead - javascript

I'm adding ESLint to my Node project and cannot figure out how to change this code to work properly:
const connection = {};
for (let [prop, value] of connectionString) {
prop = prop.split(' ')[0];
connection[prop] = value;
}
I'm getting error:
'value' is never reassigned. Use 'const' instead.

Rather than reassigning prop, create a new variable for the first word. That way, both prop and value can be declared with const:
const connection = {};
for (const [prop, value] of connectionString) {
const firstWord = prop.split(' ')[0];
connection[firstWord] = value;
}
Most of the time, clean readable code can work just fine without ever reassigning a variable. Best to only reassign an existing variable when you absolutely have to - that's a big part of why the rule exists, to prod you to use const (and produce more readable code as a result).
You could also achieve it without the intermediate variable:
const connection = {};
for (const [prop, value] of connectionString) {
connection[prop.split(' ')[0]] = value;
}

Related

New property assignment to object leads to weird behaviour in NodeJS

On a recent interview process, I was asked to write code for an API.
I used NodeJS, v16.14.0.
However, I encountered some very weird behavior:
module.exports = {
findSomething: (data) => {
const keys = Object.keys(data).sort();
let maxObj = null;
let maxKey = null;
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
const currObj = data[key];
if (maxObj == null || currObj.prop > maxObj.prop) {
maxObj = currObj;
maxKey = key;
}
}
// Attempt to assign a new property to the object:
// Variant 1, causes odd behaviour.
maxObj.maxKey = maxKey;
// Variant 2, object copy - works OK.
let newData = {...maxObj}
newData.maxKey = maxKey;
return newData;
}
}
This very minor change (Variant 1 instead of 2), gave no errors, however led the function behave very oddly. sometimes producing right results and others just nothing.
This led me to lose precious time, and eventually I was stunned to find it out.
I am not aware of cases of such behaviour. As I want to learn from this and get better, are you aware of why this could possibly happen, or if I am missing something obvious here? I know that assigning a new property to an existing object is fine in JavaScript, and my variables were all within scope usage.

How to refactor/fix algorithim from mutating a reference to using inline variable

The function takes an input path like a.b.c and should output a nested structure json like:
{
a: {
b: {
c: {}
}
}
}
The algorithm using iterative style is:
function stringToObj(path, obj) {
var parts = path.split(".");
var part;
while ((part = parts.shift())) {
if (typeof obj[part] != "object") obj[part] = {};
obj = obj[part]; // line 6
}
}
Current usage:
let result = {};
stringToObj("a.b.c", result);
console.log(result); // outputs the json
JsFiddle
The problem:
It relies mutating the obj parameter on line 6.
I would like to not rely upon passing the result object, and rather create one inside the function. Doing so results in different results. A desired example usage:
const result = stringToObj("a.b.c"); // result should be the json
Context:
The exercise is for learning purpose. Main objective is understanding why removing obj and rewriting the function as per follows doesn't work as expected:
function stringToObj(path) {
var obj = {};
var parts = path.split(".");
var part;
while ((part = parts.shift())) {
if (typeof obj[part] != "object") obj[part] = {};
obj = obj[part]; // line 6
}
return obj;
}
After splitting by .s, you can use reduceRight to start at the last property, c, while taking an initial value of an empty object. Inside the callback, use a computed property to return a new object containing the old object at the property being iterated over:
const stringToObj = str => str.split('.').reduceRight(
(lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));
If you're not familiar with it, reduceRight is like reduce, except that it iterates starting from the last element in the array and going backwards, instead of starting from the first element of the array and going forwards. On each iteration, the callback is called, where the first argument (here, lastObj) is the value returned from the last iteration, and the second argument is the current item of the array being iterated over.
You can also reverse the array of properties and use reduce instead of reduceRight, which might be easier to understand at a glance, but it's a bit less elegant:
const stringToObj = str => str.split('.').reverse().reduce(
(lastObj, prop) => ({ [prop]: lastObj }), {}
);
console.log(stringToObj('a.b.c'));
Also, don't mix var and let. If you're going to use ES2015 syntax - which you should - consider always using const, and only use let when you must reassign. Never use var, it has too many gotchas to be worth using in modern code.

How to destructure obj[arr[0]] = arr[1]

Given the following code eslint throws a prefer-destructuring error at me:
const params = {};
const splitted = 'key=value'.split('=');
params[splitted[0]] = splitted[1];
How can I use destructuring in the third line?
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
Try the below example, it assign value at zero index to key variable and value at first index to value variable.
const params = {};
const [key,value] = 'key=value'.split('=');
params[key] = value;
console.log(params);

JS rename an object key, while preserving its position in the object

My javascript object looks like this:
const someObj = {
arr1: ["str1", "str2"],
arr2: ["str3", "str4"]
}
In attempting to rename a key (e.g. arr1), I end up deleting the existing key and writing a new key with the original value. The order of obj changes.
someObj = {
arr2: ["str3", "str4"],
renamedarr1: ["str1", "str2"]
}
How do I rename a key while preserving the key order?
In the end it was solved in a js-vanila way rather than a react way.
In case somebody would look for a similar solution, I am posting the code I ended up using. Inspired by Luke's idea:
const renameObjKey = ({oldObj, oldKey, newKey}) => {
const keys = Object.keys(oldObj);
const newObj = keys.reduce((acc, val)=>{
if(val === oldKey){
acc[newKey] = oldObj[oldKey];
}
else {
acc[val] = oldObj[val];
}
return acc;
}, {});
return newObj;
};
You might want to consider reducing the array of keys into a new object.
To do this, you need also to know which key changed to what.
Reduce the array of keys
use a reducer which checks for a key change, and change it if necessary.
add the key to the object with the value
After that you have a Object with the order you had before, and possibly a changed key is still at the same position
Something like this might work (not tested)
const changedKeyMap = {"previousKey": "newKey"};
const keys = Object.keys(this.state.obj);
const content = e.target.value;
const result = keys.reduce((acc, val) => {
// modify key, if necessary
if (!!changedKeyMap[val]) {
val = changedKeyMap[val];
}
acc[val] = content;
// or acc[val] = this.state.obj[val] ?
return acc;
}, {});
As you can see, you need to keep track of how you changed a key (changedKeyMap).
The reduce function just iterates over all keys in correct order and adds them to a newly created object. if a key is changed, you can check it in the changedKeyMap and replace it. It will still be at the correct position

How to declare a nested Javascript object in one statement with variable keys

This is probably something that Ruby does better, but is there a better way to write this Javascript code (for React):
handleCellChange: function(rowIdx, prop, val) {
var updateObj = {};
updateObj.data = {};
updateObj.data[rowIdx] = {};
updateObj.data[rowIdx][prop] = { $set: val };
var newState = React.addons.update(this.state, updateObj);
In ES6 you can use computed property names:
updateObj = { data: { [rowIdx]: { [prop]: {$set: val} } } };
You can use this in Traceur or Firefox nightly, etc. (but not yet in node --harmony).
Here is a thing which will transpile this syntax for you: https://www.npmjs.org/package/es6-computed-property-keys.
For more information see http://wiki.ecmascript.org/doku.php?id=harmony:object_literals#object_literal_computed_property_keys. Also see "computed properties" item in http://kangax.github.io/compat-table/es6/#.
Javascript's object literal notation (pre-ES6) has no provision for variable keys. You could reduce the number of assignments a bit, though:
handleCellChange: function(rowIdx, prop, val) {
var updateObj = { data: {} };
(updateObj.data[rowIdx] = {})[prop] = { $set: val };
You may or may not consider that any improvement - more concise, but probably less readable. I would wholeheartedly recommend that you add the nested data object to the initial assignment to updateObj (which should be declared with var, btw) as I did above. However, using the result of the initialization of data[rowIdx] as a value that you then index on the same line is of rather more questionable value.

Categories

Resources