40

这是一个例子:

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

const { a, ...rest } = initObject

我们a从对象中省略了属性,但随后const a被分配了一个值,但从未使用过 - 来自 eslint 的错误(no-unused-vars)。可以完全省略const a吗?

4

8 回答 8

34

一种可能的方法是使用// eslint-disable-next-line no-unused-vars

例如

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

或者通过使用ignoreRestSiblings

ignoreRestSiblings 选项是一个布尔值(默认值:false)。使用 Rest 属性可以从对象中“省略”属性,但默认情况下,兄弟属性被标记为“未使用”。启用此选项后,其余属性的兄弟姐妹将被忽略。

例如

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

更多信息no-unused-vars


但是,如果您的目标是删除属性a,还有另一种方法。
您可以使用delete运算符。

来自MDN 文档

JavaScript运算符从对象中删除属性delete

例如

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

const rest = { ...initObject }; // create a shallow copy
delete rest.a;

console.log(rest);

于 2019-05-15T14:34:18.637 回答
16
于 2019-05-15T21:24:37.213 回答
8

这似乎与@R3tep 的答案略有偏差,但它避免了将声明中的所有变量标记为已使用的陷阱:

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

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

现在如果rest未使用,它仍然会导致 eslint 错误。


关于这个问题

那么删除属性的正确方法是什么?

我将回答你应该问的问题。处理具有您不需要的属性的对象的正确方法是以隐式忽略它们的方式重写您的逻辑。

  1. 如果您只需要属性bc,则仅解构这些属性:

    const { b, c } = initObject
    

    a如果你不需要它,甚至不要承认它的存在。

  2. 如果您的输入有很多您需要处理的特定属性,并且您不能假设initObject已经具有所需的确切布局,那么请避免使用反射方法或语法,例如,Object.entries()对象传播和休息语法等.for...in

    继续单独处理您需要的特定属性,并将您的逻辑分解为可分离的函数,如果需要,每个函数都处理可管理的属性子集。

    另一方面,如果您可以预先设置输入以具有您已经需要的确切布局(例如,您可以假设initObject只有band c),那么请随意使用反射——这正是它的用途。

  3. 如果以上两点都不适用于您,并且您仍然发现您确实想要initObject拥有很多任意属性,并且您想忽略一些属性,那么您应该使用此答案开头的建议(或一个其他适合您的答案)。

    但是,如前所述,这是代码异味,表明您的逻辑需要对对象1的布局更加宽容,或者您​​的输入前提条件需要更改2

于 2019-05-15T14:45:23.957 回答
2

技术上满足 linter 规则的一个选项是预先声明,将属性rest解构为,然后使用 rest 语法将对象的其余部分放入变量名中:arestrest

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

console.log(rest);

不幸的是,如果你想避免var,你不能像

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

因为当左侧{声明一个变量时,右侧的每个新变量名都是单独初始化的——也就是说,对于解释器来说,它看起来有点像

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

let但不允许相同变量名称的重复标识符。您可以在一行中使用var,允许重复标识符:

const initObject = {
  a: 0,
  b: 0,
  c: 0
};
var { a: rest, ...rest } = initObject;

console.log(rest);

但这有点奇怪。正如其他答案所建议的那样,我更喜欢配置/忽略 linter,或者使用解构以外的东西。

于 2019-05-15T22:07:01.913 回答
2

您可以创建一个 IIFE 并将对象传递给它。

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

于 2019-05-15T14:25:40.743 回答
1

您可以使用创建对象的浅表副本Object.assign()并简单地删除该属性。

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

let rest = Object.assign({}, initObject);
delete rest.a;

console.log(rest);
console.log(initObject);

于 2019-05-15T14:28:16.743 回答
1

尝试

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

'use strict'

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

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

console.log({initObject,rest});

于 2019-05-15T14:31:09.140 回答
0

为了省略(清理) ID 和密码属性,这最终在一个对象中对我有用。

这是来自产品和用户模型之间的关系的回应。

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

否则,对于数组,我使用:

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

我正在使用 PostgreSQL、Nest、Objection 和 Knex。

于 2020-09-14T01:16:31.030 回答