简体   繁体   English

使用对象解构时省略属性变量

[英]Omit property variable when using object destructuring

Here is an example:下面是一个例子:

const initObject = {
  a: 0,
  b: 0,
  c: 0
}

const { a, ...rest } = initObject

We're omitting property a from the object, but then const a is assigned a value, but never used - error from eslint (no-unused-vars).我们从对象中省略了属性a ,但随后为const a分配了一个值,但从未使用过 - 来自 eslint (no-unused-vars) 的错误。 Is it possible to completely omit const a ?是否可以完全省略const a

A possible way is to use // eslint-disable-next-line no-unused-vars一种可能的方法是使用// eslint-disable-next-line no-unused-vars

eg例如

// eslint-disable-next-line no-unused-vars
const { a, ...rest } = initObject

Or by usingignoreRestSiblings或者通过使用ignoreRestSiblings

The ignoreRestSiblings option is a boolean (default: false). ignoreRestSiblings 选项是一个布尔值(默认值:false)。 Using a Rest Property it is possible to “omit” properties from an object, but by default the sibling properties are marked as “unused”.使用 Rest 属性可以从对象中“省略”属性,但默认情况下,同级属性被标记为“未使用”。 With this option enabled the rest property's siblings are ignored.启用此选项后,其余属性的同级将被忽略。

eg例如

/*eslint no-unused-vars: ["error", { "ignoreRestSiblings": true }]*/
// 'a' is ignored because it has a rest property sibling.
const { a, ...rest } = initObject;

More info about no-unused-vars有关no-unused-vars更多信息


But if your goal is to remove the property a , there is another way.但如果您的目标是删除属性a ,还有另一种方法。
You can use delete operator.您可以使用delete运算符。

From MDN documentation来自MDN 文档

The JavaScript delete operator removes a property from an object JavaScript delete运算符从对象中删除属性

eg例如

 const initObject = { a: 0, b: 0, c: 0 } const rest = { ...initObject }; // create a shallow copy delete rest.a; console.log(rest);

error from eslint (no-unused-vars).来自 eslint 的错误(no-unused-vars)。

The no-unused-vars rules has two configuration options that will help with your use case: no-unused-vars 规则有两个配置选项可以帮助您处理用例:

  • TheignoreRestSiblings option is a boolean that defaults to false . ignoreRestSiblings选项是一个默认为false的布尔值。 When enabled, the rest property's siblings are ignored.启用后,其余属性的同级将被忽略。 This is exactly what you need!正是您所需要的!
  • The varsIgnorePattern option specifies a regexp pattern for variable names not to be checked for usage. varsIgnorePattern选项指定不检查使用情况的变量名称的正则表达式模式。 This allows us to make an exception for the common underscore identifier to explicitly mark unused variables with { "varsIgnorePattern": "^_" } .这允许我们对常见的下划线标识符进行例外处理,以使用{ "varsIgnorePattern": "^_" }显式标记未使用的变量。

     const { a:_, ...rest } = initObject; // ^^

    Unfortunately you still need to avoid multiple declarations of the _ variable, so to omit multiple properties you'd need to do something like { a:_a, b:_b, ...rest } = … .不幸的是,您仍然需要避免_变量的多个声明,因此要省略多个属性,您需要执行类似{ a:_a, b:_b, ...rest } = …

Is it possible to completely omit const a ?是否可以完全省略const a

A bad hack that completely avoids introducing any identifier would be to use一个完全避免引入任何标识符的坏黑客是使用

const { a:{}, ...rest } = initObject;
//       ^^^

that further destructures the .a property value into an object, but for this you need to ensure that the property exists and doesn't hold a null or undefined value.这进一步将.a属性值解构为一个对象,但为此您需要确保该属性存在并且不包含nullundefined值。

This may seem a trivial deviation from @R3tep's answer , but it avoids the pitfall of marking all the variables in the declaration as used:这似乎与@R3tep 的回答略有偏差,但它避免了将声明中的所有变量标记为使用的陷阱:

const initObject = {
  a: 0,
  b: 0,
  c: 0
}

const {
  a, // eslint-disable-line no-unused-vars
  ...rest
} = initObject

Now if rest is unused, it will still cause an eslint error.现在如果rest没有使用,它仍然会导致 eslint 错误。


In regards to the question关于这个问题

what's the correct way to remove a property then?那么删除属性的正确方法是什么?

I'm going to answer the question you should have asked instead.我要回答你应该问的问题。 The correct way to handle an object with properties you don't need is to rewrite your logic in a way that implicitly ignores them.处理具有不需要属性的对象的正确方法是以隐式忽略它们的方式重写逻辑。

  1. If you just need the properties b and c , destructure only those properties:如果您只需要属性bc ,请仅解构这些属性:

     const { b, c } = initObject

    Don't even acknowledge that a exists if you don't need it.甚至不承认a ,如果你不需要它的存在。

  2. If your input has a lot of specific properties you need to deal with, and you can't assume that initObject already has the exact layout it needs, then avoid the temptation to use reflection methods or syntax like Object.entries() , for...in , object spread and rest syntax , etc.如果你的输入有很多你需要处理的特定属性,并且你不能假设initObject已经有它需要的确切布局,那么避免使用反射方法或像Object.entries()这样的语法的诱惑for...in对象传播和休息语法等。

    Continue to handle the specific properties you need on an individual basis, and break up your logic into separable functions that each deal with a manageable subset of the properties, if necessary.继续单独处理您需要的特定属性,并在必要时将您的逻辑分解为可分离的函数,每个函数处理可管理的属性子集。

    On the other hand, if you can precondition your input to have the exact layout you already need (eg you are able to assume that initObject only has b and c ), then feel free to use reflection -- that's exactly what it's for.另一方面,如果您可以预先调整您的输入以获得您已经需要的确切布局(例如,您可以假设initObject只有bc ),那么可以随意使用反射——这正是它的用途。

  3. If neither of the above two points applies to you and you still find that you really want initObject to have a lot of arbitrary properties, and a few that you want to ignore, then you should use the suggestion at the beginning of this answer (or one of the other answers that works for you).如果以上两点都不适用于您,并且您仍然发现您确实希望initObject具有许多任意属性,并且有一些您想忽略,那么您应该使用本答案开头的建议(或对您有用的其他答案之一)。

    However, as noted, this is code-smell and an indicator that your logic needs to be more lenient with the layout of the object 1 , or your preconditions for the input need to change 2 .但是,如前所述,这是代码味道,并且表明您的逻辑需要对对象1的布局更加宽松,或者您的输入前提条件需要更改2

You can create a IIFE and pass object to it.您可以创建一个 IIFE 并将对象传递给它。

 const initObject = { a: 0, b: 0, c: 0 } const res = (({a,...rest}) => (a,rest))(initObject); console.log(res)

An option that technically fulfills the linter rules would be to declare rest upfront, destructure the a property into rest , and then use rest syntax to put the rest of the object into the rest variable name:技术上满足 linter 规则的一个选项是预先声明rest ,将a属性解构为rest然后使用 rest 语法将对象的rest放入rest变量名称中:

 const initObject = { a: 0, b: 0, c: 0 }; let rest; ({ a: rest, ...rest } = initObject); console.log(rest);

Unfortunately, if you want to avoid var , you can't do it in just a single line like不幸的是,如果你想避免var ,你不能像这样在一行中完成

let { a: rest, ...rest } = initObject

because when the left-hand side of the { declares a variable, each new variable name on the right side is initialized separately - that is, to the interpreter it looks a bit like因为当{的左侧声明一个变量时,右侧的每个新变量名都被单独初始化——也就是说,对于解释器来说,它看起来有点像

let rest = initObject.a;
let rest = <everything else in initObject>

But duplicate let identifiers for the same variable name is not permitted.但是不允许为相同的变量名称使用重复的let标识符。 You could do it in one line with var , for which duplicate identifiers are permitted:可以在一行中使用var ,其中允许使用重复的标识符:

 const initObject = { a: 0, b: 0, c: 0 }; var { a: rest, ...rest } = initObject; console.log(rest);

But this is all a little bit odd.但这一切都有些奇怪。 I'd prefer to configure/ignore the linter, or use something other than destructuring, as other answers have suggested.正如其他答案所建议的那样,我更愿意配置/忽略 linter,或者使用解构以外的其他方法。

You can create a shallow copy of the object using Object.assign() and simply delete the property.您可以使用Object.assign()创建对象的浅表副本,然后简单地删除该属性。

 const initObject = { a: 0, b: 0, c: 0 } let rest = Object.assign({}, initObject); delete rest.a; console.log(rest); console.log(initObject);

try尝试

const rest = ((o)=> (delete o.a,o))({...initObject});

 'use strict' const initObject = { a: 0, b: 0, c: 0 } const rest = ((o)=> (delete oa,o))({...initObject}); console.log({initObject,rest});

In order to omit (sanitize) the ID and the password properties, this is what finally worked for me in a single object.为了省略(清理)ID 和密码属性,这最终在单个对象中对我有用。

This was the response from a Relationship between Products and Users Models.这是来自产品和用户模型之间的关系的响应。

   return {...product,
        author: [
            `username: ` + product['author'].username,
            `email: ` + product['author'].email,
        ]};

Otherwise for an array, I used:否则对于数组,我使用:

    return products.map(product => [{ 
        'title' : product['title'],
        'description' : product['description'],
        'price' : product['price'],
        'updated' : product['updatedAt'],
        'author': {
            'username' : product['author'].username,
            'email' : product['author'].email,
        },                   
    }]);

I'm using PostgreSQL, Nest, Objection and Knex.我正在使用 PostgreSQL、Nest、Objection 和 Knex。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM