在 DOM 对象上设置 属性 时如何避免无参数重新分配

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

我有一个主要目的是在 DOM 对象上设置 属性 的方法

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

我使用 AirBnB 的代码风格,这使得 ESLint 抛出 no-param-reassign 错误:

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

如何在符合 AirBnB 代码风格的同时操作作为参数传递的 DOM 对象?

有人建议使用 /* eslint react/prop-types: 0 */ 指的是 但如果我没记错的话这适用于反应,但不适用于原生 DOM 操作。

我也不认为改变代码风格是一个答案。我相信使用标准风格的好处之一是在项目之间拥有一致的代码,随意更改规则感觉就像滥用了像 AirBnB 这样的主要代码风格。

郑重声明,我在 GitHub 上询问了 AirBnB,他们认为在这些情况下应该怎么走 in issue #766

正如@Mathletics 所建议的,您可以 disable the rule 完全通过将其添加到您的 .eslintrc.json 文件中:

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

或者您可以禁用专门针对参数属性的规则:

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

或者,您可以禁用该功能的规则:

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

或仅针对特定行:

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

您可以在 .eslintrc 文件中覆盖此规则,并针对这样的参数属性禁用它

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

这种方式规则仍然有效,但不会对属性发出警告。 更多信息:http://eslint.org/docs/rules/no-param-reassign

您可以使用:

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

那些希望有选择地停用此规则的人可能对 no-param-reassign 规则的 proposed new option 感兴趣,该规则将允许 "white list" 对象名称,其中参数重新分配应该是忽略。

您还可以使用 lodash assignIn 来改变对象。 assignIn(obj, { someNewObj });

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

作为this article explains, this rule is meant to avoid mutating the arguments object。如果您分配给一个参数,然后尝试通过 arguments 对象访问某些参数,可能会导致意外结果。

您可以通过使用另一个变量获取对 DOM 元素的引用然后修改该元素来保持规则不变并保持 AirBnB 风格:

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

在JS中对象(包括DOM节点)是通过引用传递的,所以这里eltheElement是对同一个DOM节点的引用,但是修改theElement 不会改变 arguments 对象,因为 arguments[0] 仍然只是对 DOM 元素的引用。

documentation for the rule:

中暗示了这种方法

Examples of correct code for this rule:

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

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

就我个人而言,我只会使用 "no-param-reassign": ["error", { "props": false }] 方法提到的其他几个答案。修改作为参数传递的对象的 属性 不会更改对象引用,因此它不应该 运行 成为此规则试图避免的问题类型。

您可以使用更新数据的方法。例如。 "res.status(404)" 而不是 "res.statusCode = 404" 我找到了解决方案。 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;
});

documentation之后:

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

no-param-reassign 警告对于常见函数有意义,但对于经典的 Array.forEach 循环遍历您打算改变的数组是不合适的。

但是,要解决此问题,您还可以将 Array.map 与新对象一起使用(如果您像我一样,不喜欢带有注释的暂停警告):

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

其他一切都是丑陋的技巧。

如果您真的不想禁用该规则,更新后的替代方案可能类似于:

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

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

根据 eslint (https://eslint.org/docs/2.0.0/rules/no-param-reassign) 的文档,我使用 .eslintrc.js 文件中的以下书面配置解决了它。

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