How to avoid no-param-reassign when setting a property on a DOM object

JavascriptDomEslint

Javascript Problem Overview


I have a method which's main purpose is to set a property on a DOM object

function (el) {
  el.expando = {};
}

I use AirBnB's code style which makes ESLint throw a no-param-reassign error:

> error Assignment to function parameter 'el' no-param-reassign

How can I manipulate a DOM object passed as an argument while conforming AirBnB's code style?

Somebody suggested to use /* eslint react/prop-types: 0 */ referring to another issue but if I am not mistaken this applies well for react, but not for native DOM manipulation.

Also I do not think changing the code style is an answer. I believe one of the benefits of using a standard style is having consistent code across projects and changing the rules at will feels like a misuse of a major code style like AirBnB's.

For the record, I asked AirBnB on GitHub, what they think is the way to go in these cases in issue #766.

Javascript Solutions


Solution 1 - Javascript

As @Mathletics suggests, you can disable the rule entirely by adding this to your .eslintrc.json file:

"rules": {
  "no-param-reassign": 0
}

Or you can disable the rule specifically for param properties:

"rules": {
  "no-param-reassign": [2, { "props": false }]
}

Alternatively, you can disable the rule for that function:

/* eslint-disable no-param-reassign */
function (el) {
  el.expando = {};
}
/* eslint-enable no-param-reassign */

Or for a specific line only:

function (el) {
  el.expando = {}; // eslint-disable-line no-param-reassign
}

Solution 2 - Javascript

As this article explains, this rule is meant to avoid mutating the arguments object. If you assign to a parameter and then try and access some of the parameters via the arguments object, it can lead to unexpected results.

You could keep the rule intact and maintain the AirBnB style by using another variable to get a reference to the DOM element and then modify that:

function (el) {
  var theElement = el;
  theElement.expando = {};
}

In JS objects (including DOM nodes) are passed by reference, so here el and theElement are references to the same DOM node, but modifying theElement doesn't mutate the arguments object since arguments[0] remains just a reference to that DOM element.

This approach is hinted at in the documentation for the rule:

> Examples of correct code for this rule:

/*eslint no-param-reassign: "error"*/

function foo(bar) {
    var baz = bar;
}

Personally, I would just use the "no-param-reassign": ["error", { "props": false }] approach a couple of other answers mentioned. Modifying a property of an object that was passed as a parameter doesn't change the object reference, so it shouldn't run into the kinds of problems this rule is trying to avoid.

Solution 3 - Javascript

You can override this rule inside your .eslintrc file and disable it for param properties like this

{
    "rules": {
        "no-param-reassign": [2, { 
            "props": false
        }]
    },
    "extends": "eslint-config-airbnb"
}

This way rule is still active but it will not warn for properties. More info: http://eslint.org/docs/rules/no-param-reassign

Solution 4 - Javascript

The no-param-reassign warning makes sense for common functions, but for a classic Array.forEach loop over an array which you intend to mutate it isn't to appropriate.

However, to get around this, you can also use Array.map with a new object (if you are like me, dislike snoozing warnings with comments):

someArray = someArray.map((_item) => {
    let item = Object.assign({}, _item); // decouple instance
    item.foo = "bar"; // assign a property
    return item; // replace original with new instance
});

Solution 5 - Javascript

function (el) {
  el.setAttribute('expando', {});
}

Everything else is just ugly hacks.

Solution 6 - Javascript

Those wishing to selectively deactivate this rule might be interested in a proposed new option for the no-param-reassign rule that would allow a "white list" of object names with respect to which parameter reassignment should be ignored.

Solution 7 - Javascript

You can also use lodash assignIn which mutates the object.

assignIn(obj, { someNewObj });

https://lodash.com/docs/4.17.2#assignIn

Solution 8 - Javascript

Following the documentation:

function (el) {
  const element = el
  element.expando = {}
}

Solution 9 - Javascript

An updated alternative if you don't really want to disable the rule, could be something like:

function (el) {
  Object.defineProperty(el, 'expando',{
    value: {},
    writable: true,
    configurable: true,
    enumerable: true
  });
}

Reference : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

Solution 10 - Javascript

You can use methods for updating data. Eg. "res.status(404)" instead of "res.statusCode = 404" I found the solution. https://github.com/eslint/eslint/issues/6505#issuecomment-282325903

/*eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsFor": ["$scope"] }]*/

app.controller('MyCtrl', function($scope) {
  $scope.something = true;
});

Solution 11 - Javascript

Based on the documentation at eslint (https://eslint.org/docs/2.0.0/rules/no-param-reassign), I solved it using the below written configuration in the .eslintrc.js file.

rules: {
  "no-param-reassign": [2, {"props": false}]
},

Solution 12 - Javascript

You can use:

(param) => {
  const data = Object.assign({}, param);
  data.element = 'some value';
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLukasView Question on Stackoverflow
Solution 1 - JavascriptsfletcheView Answer on Stackoverflow
Solution 2 - JavascriptUseless CodeView Answer on Stackoverflow
Solution 3 - JavascriptGyandeepView Answer on Stackoverflow
Solution 4 - JavascriptJustus RomijnView Answer on Stackoverflow
Solution 5 - Javascriptavalanche1View Answer on Stackoverflow
Solution 6 - JavascriptRH BeckerView Answer on Stackoverflow
Solution 7 - JavascriptJazzyView Answer on Stackoverflow
Solution 8 - JavascriptVictor SantosView Answer on Stackoverflow
Solution 9 - JavascriptmgaspView Answer on Stackoverflow
Solution 10 - JavascriptViktor AntishovView Answer on Stackoverflow
Solution 11 - JavascriptAvijit MajhiView Answer on Stackoverflow
Solution 12 - JavascriptOliverView Answer on Stackoverflow