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

我有一个方法,它的主要用途是在 DOM 对象上设置一个属性

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

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

函数参数‘ el’的错误分配

如何操作作为参数传递的 DOM 对象,同时遵循 AirBnB 的代码风格?

有人建议使用 /* eslint react/prop-types: 0 */引用 另一个问题,但是如果我没有弄错的话,这适用于反应,但不适用于本机 DOM 操作。

我也不认为改变代码样式是一个答案。我相信使用标准样式的好处之一就是在不同的项目中拥有一致的代码,而且随意改变规则就像是对 AirBnB 这样的主要代码样式的滥用。

郑重声明,我在 GitHub 上问过 AirBnB,他们认为在这种情况下 第766期应该怎么做。

185222 次浏览

正如@Mathletics 所建议的,你完全可以通过将其添加到 .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"
}

这种方式规则仍然是活动的,但不会对属性发出警告。 更多信息: < a href = “ http://eslint.org/docs/rules/no-param-re堆”> http://eslint.org/docs/rules/no-param-reassign

你可使用:

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

那些希望有选择地停用这个规则的人可能对 no-param-reassign规则的 提议的新方案感兴趣,这个 no-param-reassign规则允许一个对象名称的“白名单”,关于这个对象名称的参数重新分配应该被忽略。

您还可以使用 lodashassignIn来变更对象。 SignIn (obj,{ some NewObj }) ;

Https://lodash.com/docs/4.17.2#assignin

作为 这篇文章解释了,这个规则是为了避免 arguments物体的突变。如果您分配给一个参数,然后尝试通过 arguments对象访问一些参数,那么可能会导致意外的结果。

你可以使用另一个变量来获得对 DOM 元素的引用,然后修改它,从而保持规则的完整性和 AirBnB 风格:

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

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

规则文件中暗示了这种方法:

此规则的正确代码示例:

/*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;
});

按照 文件:

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

no-param-reassign警告对于常见函数是有意义的,但是对于经典的 Array.forEach循环,如果您打算对数组进行变异,那么就不适合使用 no-param-reassign警告。

但是,为了避免这个问题,你也可以在新对象中使用 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}]
},

您可以使用扩展运算符创建一个副本,并且只更改1个属性。

function (el) {
var editedEl = { ...el, expando: {} };
}

然后继续使用 editedEl