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


94

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

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

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

错误分配给功能参数“ el”的无参数重新分配

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

有人建议用/* eslint react/prop-types: 0 */指的是另一个问题,但如果我没有弄错的适用以及为反应,而不是原生DOM操作。

我也不认为更改代码样式是解决方案。我相信使用标准样式的好处之一是跨项目具有一致的代码,并且随意更改规则感觉就像滥用AirBnB这样的主要代码样式一样。

作为记录,我在GitHub上问了AirBnB,他们认为在这些有争议的案例#766中该怎么办。


没事 首先,这将意味着在该规则有意义的所有其他情况下禁用此功能。其次,我相信您要么遵循样式指南,要么不遵循。至少,如果这是样式指南,许多项目开发人员都会遵循它。
卢卡斯2016年

2
但是您正在问如何遵守样式指南,因为您正在做它试图防止的事情。无论如何,只需禁用该功能即可
Mathletics


@Mathletics不,我觉得该规则很明智,但不适用于此特定情况。我想知道是否有办法按照规则进行这项工作。
卢卡斯2016年

无论您如何措辞,您想要的操作都与规则冲突。也就是说,这似乎是XY问题;我不会像这样直接将属性附加到DOM节点。
Mathletics '16

Answers:


100

正如@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
}

您也可以查看 有关禁用ESLint规则的博客文章,以专门适应AirBnB的样式指南。


1
谢谢。似乎大多数人发现修改短绒棉是最好的方法。现在,将其应用于单行似乎是最佳的权衡。
卢卡斯

2
这确实是有意义的,即表达的NodeJS项目,其中有时你可能需要修改res.session马上
大卫

如果问题仅在于问题中所述的设置函数参数的属性,则Gyandeep的以下答案要好得多。
Prashanth Chandra

84

本文所述,此规则旨在避免使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 }]方法提及的其他两个答案。修改参数的属性不会使该参数所引用的内容发生变化,也不应遇到该规则试图避免的问题。


5
这应该是公认的答案,而不是规避行为的方法。自从得到这个答案以来,ESLint官方文档中所述的Patric Bacon指出了在某些情况下可能发生的明显问题:spin.atomicobject.com/2011/04/10/…–
Remi,

1
该答案应为公认的答案,因为它指向的是官方文档,并且经过了充分说明。其他大多数答案就像关闭火警警报一样!
Hamid Parchami

您可能会收到“局部变量'theElement'是多余的”。
范遵映

您将为这些新参考使用哪种命名方案?我绝对不喜欢将“我的”放在这里,但是在创建新引用时重命名已经适当命名的参数确实非常困难,甚至违反直觉。
GhostBytes

我刚刚检查arguments[0]并被变异。我究竟做错了什么?... theElement.expando = { p: 2 }; return arguments[0].expando; ...
mrmowji

20

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

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

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


3
这个答案不完全包含在接受的答案中吗?
Dan Dascalescu

1
@DanDascalescu在已接受答案的下方有一条评论指向该答案,因此也许在某个时候对其进行了编辑以便更全面?
bigsee '19

11

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

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

其他一切都只是丑陋的骇客。


2

那些希望选择停用此规则可能会感兴趣的提出了新的选项no-param-reassign,将允许对象名称的“白名单”相对于该参数重新分配应该被忽略的规则。


由于缺少代表点,以上内容被发布为答案,而不是评论。
RH Becker




-1

您可以使用:

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

1
这不是只修改副本吗(那有多有价值)?
2540625'6

1
这并不是真正的解决方案,因为这意味着通过创建一个新对象来避免参数重新分配,而我明确不需要创建新对象,而需要修改原始对象。
卢卡斯

我不想修改参数,但是如果这样做,您也可以使用Object.defineProperty(),这样棉绒就不会抛出错误。
奥利弗(Oliver)

这根本行不通。您正在制作变量的副本,将其属性复制到新对象上,修改属性然后不返回它,因此什么也没有发生。即使您确实返回了它,也将返回一个对象,而不是返回的DOM元素。最重要的是,它Object.assign是用于从一个对象复制到一个目标对象。试图从这样的DOM元素中复制会导致一个空对象。
无用的代码,

Object.assign如果您尝试使用循环引用(例如套接字连接)重新声明Object的属性,那么Plus 将无法正常工作。Object.assign默认情况下是浅表副本,由于性能下降,深层克隆很不受欢迎。
ILikeTacos

-1

如果要更改对象数组内的任何值,可以使用

array.forEach(a => ({ ...a, expando: {} }))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.