在 DOM 对象上设置属性时如何避免 no-param-reassign
Posted
技术标签:
【中文标题】在 DOM 对象上设置属性时如何避免 no-param-reassign【英文标题】:How to avoid no-param-reassign when setting a property on a DOM object 【发布时间】:2016-06-08 20:17:15 【问题描述】:我有一个主要目的是在 DOM 对象上设置属性的方法
function (el)
el.expando = ;
我使用 AirBnB 的代码风格,这使得 ESLint 抛出 no-param-reassign
错误:
错误赋值给函数参数'el' no-param-reassign
如何操作作为参数传递的 DOM 对象,同时符合 AirBnB 的代码样式?
有人建议使用/* eslint react/prop-types: 0 */
指代another issue,但如果我没记错的话,这适用于react,但不适用于本机DOM 操作。
我也不认为改变代码风格是一个答案。我相信使用标准样式的好处之一是在项目之间具有一致的代码,并且随意更改规则感觉就像对 AirBnB 等主要代码样式的滥用。
为了记录,我在 GitHub 上询问了 AirBnB,他们认为在这些情况下该怎么办in issue #766。
【问题讨论】:
不。首先,这意味着在该规则有意义的所有其他事件中禁用它。其次,我相信您要么遵循样式指南,要么不遵循。至少如果它是各种项目的许多开发人员遵循的风格指南。 但是你在问如何不遵守风格指南,因为你正在做它试图阻止的事情。无论如何,只需disable it for that function How to disable ESLint react/prop-types rule in a fil?的可能重复 @Mathletics 不,我觉得这条规则很有意义,但它不适用于这种特定情况。我想知道是否有办法按照规则来做到这一点。 不管怎么说,你想要的操作都与规则冲突。也就是说,这似乎是一个 XY 问题。我不会像那样将属性直接附加到 DOM 节点。 【参考方案1】:正如@Mathletics 建议的那样,您可以通过将其添加到您的.eslintrc.json
文件中来完全disable the rule:
"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
【讨论】:
谢谢。似乎大多数人发现修改 linter 是最好的方法。对我来说,将其应用于单行似乎是最好的折衷方案。 这真的很有意义,即对于 nodejs express 项目,有时您可能想立即修改res.session
如果问题仅在于设置问题中所述的函数参数的属性,那么 Gyandeep 下面的答案要好得多。
谢谢@hiehiuehue:看起来他们把它拿下来了。删除链接。【参考方案2】:
作为this article explains,此规则旨在避免arguments
object 发生变异。如果您分配给一个参数,然后尝试通过arguments
对象访问某些参数,则可能会导致意外结果。
您可以通过使用另一个变量来获取对 DOM 元素的引用,然后对其进行修改,从而保持规则不变并保持 AirBnB 样式:
function (el)
var theElement = el;
theElement.expando = ;
在JS中对象(包括DOM节点)是通过引用传递的,所以这里el
和theElement
是对同一个DOM节点的引用,但是修改theElement
不会改变arguments
对象,因为@987654333 @ 仍然只是对该 DOM 元素的引用。
documentation for the rule 中暗示了这种方法:
此规则的正确代码示例:
/*eslint no-param-reassign: "error"*/
function foo(bar)
var baz = bar;
就我个人而言,我只会使用"no-param-reassign": ["error", "props": false ]
方法提到的其他几个答案。修改作为参数传递的对象的属性不会更改对象引用,因此不应遇到此规则试图避免的问题。
【讨论】:
这应该是公认的答案,而不是规避行为的方法。由于这个答案和官方 ESLint 文档中所述的 Patric Bacon 指出了在某些情况下可能发生的明显问题:spin.atomicobject.com/2011/04/10/… 这个答案应该是公认的答案,因为它指向官方文档并且解释得很好。大多数其他答案就像关闭火警一样! 您可能会得到“局部变量 'theElement' 是多余的”。 修改参数的属性不会改变该参数所指的内容。,我认为对象是通过引用传递的!能详细点吗? 您在这里试图避免的“问题”实际上并不是问题。你永远不应该使用arguments
对象。相反,您应该使用rest parameters。因此可以安全地忽略 no-param-reassign。【参考方案3】:
您可以在 .eslintrc
文件中覆盖此规则,并为此类参数属性禁用它
"rules":
"no-param-reassign": [2,
"props": false
]
,
"extends": "eslint-config-airbnb"
这种方式规则仍然有效,但不会对属性发出警告。 更多信息:http://eslint.org/docs/rules/no-param-reassign
【讨论】:
这个答案不是完全包含在接受的吗? @DanDascalescu 在接受的答案下方有一条评论指向这个答案,所以也许它在某个时候被编辑过更全面?【参考方案4】:no-param-reassign
警告对于常用函数是有意义的,但对于一个经典的 Array.forEach
循环,您打算改变它的数组是不合适的。
但是,为了解决这个问题,您也可以将Array.map
与新对象一起使用(如果您像我一样,不喜欢使用 cmets 发出打盹警告):
someArray = someArray.map((_item) =>
let item = Object.assign(, _item); // decouple instance
item.foo = "bar"; // assign a property
return item; // replace original with new instance
);
【讨论】:
【参考方案5】:function (el)
el.setAttribute('expando', );
其他一切都只是丑陋的黑客。
【讨论】:
【参考方案6】:那些希望有选择地停用此规则的人可能会对proposed new option 的no-param-reassign
规则感兴趣,该规则将允许对象名称的“白名单”与哪些参数重新分配应被忽略。
【讨论】:
由于缺乏代表点,以上是作为答案而不是评论发布的。【参考方案7】:您还可以使用 lodash assignIn
来改变对象。
assignIn(obj, someNewObj );
https://lodash.com/docs/4.17.2#assignIn
【讨论】:
【参考方案8】:关注documentation:
function (el)
const element = el
element.expando =
【讨论】:
【参考方案9】:如果您真的不想禁用规则,则可以使用更新的替代方法,例如:
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
【讨论】:
【参考方案10】:您可以使用方法来更新数据。例如。 “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;
);
【讨论】:
【参考方案11】:根据 eslint (https://eslint.org/docs/2.0.0/rules/no-param-reassign) 的文档,我使用.eslintrc.js
文件中的以下书面配置解决了这个问题。
rules:
"no-param-reassign": [2, "props": false]
,
【讨论】:
【参考方案12】:你可以使用:
(param) =>
const data = Object.assign(, param);
data.element = 'some value';
【讨论】:
这不只是修改副本吗(这有什么价值)? 这并不是一个真正的解决方案,因为这意味着通过创建一个新对象来避免重新分配参数,而我明确需要不创建新对象而是修改原始对象。跨度> 我不喜欢修改参数,但是如果你这样做的话,你也可以使用 Object.defineProperty(),这样 linter 不会给你一个错误。 这根本行不通。您正在制作变量的副本,将其属性复制到新对象上,修改属性然后不返回它,因此没有任何反应。即使您确实返回了它,您也将返回一个对象,而不是像传入的那样的 DOM 元素。最重要的是,Object.assign
用于从对象复制到目标对象。尝试从这样的 DOM 元素中复制会导致空对象。
Plus Object.assign
如果您尝试使用循环引用(例如套接字连接)重新分配 Object 上的属性,则将无法正常工作。 Object.assign
默认是浅拷贝,深克隆因为性能下降非常不受欢迎。以上是关于在 DOM 对象上设置属性时如何避免 no-param-reassign的主要内容,如果未能解决你的问题,请参考以下文章
javascript教程系列43: DOM对象的dataset属性方式
如何在尚未在 DOM 中的元素上使用 jQuery 设置数据属性?
如何在 JS 和 DOM 中创建元素、设置属性、使用 innerHTML 和 appendChild