JavaScript 中的数组解构

Posted

技术标签:

【中文标题】JavaScript 中的数组解构【英文标题】:Array destructuring in JavaScript 【发布时间】:2019-02-11 07:42:03 【问题描述】:

我的 vue-js 应用中有这段代码:

methods: 
    onSubmit() 
      ApiService.post('auth/sign_in', 
        email: this.email,
        password: this.password,
      )
        .then((res) => 
          saveHeaderToCookie(res.headers);
          this.$router.push( name: 'about' );
        )
        .catch((res) => 
          this.message = res.response.data.errors[0];
          this.msgStatus = true;
          this.msgType = 'error';
        );
    ,
  

在运行 Eslint 时,我收到一条错误消息,提示 "Use array destructuring" (prefer-destructuring) 在这一行:

this.message = res.response.data.errors[0];

什么是数组解构以及如何做到这一点?请给我一个概念。我已经研究过了,但无法弄清楚。

【问题讨论】:

【参考方案1】:

解构是在赋值左侧使用类似结构的语法将右侧结构的元素分配给各个变量。例如,

let array = [1, 2, 3, 4];
let [first, _, third] = array;

解构数组[1, 2, 3] 并将单个元素分配给firstthird_ 是一个占位符,使其跳过第二个元素)。因为 LHS 比 RHS 短,4 也被忽略。相当于:

let first = array[0];
let third = array[2];

还有一个对象解构赋值:

let object = first: 1, second: 2, third: 3, some: 4;
let first, third, fourth: some = object;

相当于

let first = object.first;
let third = object.third;
let fourth = object.some;

也允许使用扩展运算符:

let [first, ...rest] = [1, 2, 3];

会将1 分配给first,并将[2, 3] 分配给rest

在你的代码中,它说你可以这样做:

[this.message] = res.response.data.errors;

The documentation on prefer-destructuring 列出了它认为“正确”的内容。

【讨论】:

FWIW,如果您不需要数组中的值,则在解构时,您不需要_(函数不是这种情况)。只需let [first, , third] = array;【参考方案2】:

U 可以将该行重写为 [this.message] = res.response.data.errors; 并且该 es-lint 错误将消失。请参阅此示例以更好地理解

var x = 
  y: 
    z: 
      w: [3, 4]
    
  
;

function foo() 
  [this.a] = x.y.z.w
  console.log(this.a);

foo() // prints 3

有关数组解构的更多信息,请see here

【讨论】:

我已经这样做了:[this.message] = res.response.data.errors[0];仍然给我同样的错误 [0] 是额外的,正如 Vikash 和我的回答中所写的那样。 哎呀,是的。谢谢@Amadan【参考方案3】:

如果您想了解有关 javascript 的信息,请务必在 MDN 上查找。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Array_destructuring

这是一个简单的解构示例:

const [a, b] = ['a', 'b'];

它是自 es6 以来可用的简写,允许以更简写的方式进行变量赋值。

原来的方式是这样的:

const arr = ['a', 'b'];
const a = arr[0];
const b = arr[1];

而 es6 的方式是这样的:

const arr = ['a', 'b'];
const [a, b] = arr;

现在关于 eslint 错误,我实际上不同意那个错误。您的代码本身应该没问题。所以你应该在 Eslint github repo 上提交一个问题,询问为什么该行会触发“prefer-destructuring”警告。

【讨论】:

"为什么该行会触发prefer-destructuring 警告" - 因为这是规则。文档中有一个明确的示例,“此规则的错误代码示例:启用arrayvar foo = array[0];”因此您可能不同意该规则并将其关闭,但提出问题询问为什么规则的功能与宣传的一样。 嗯,这很有趣@Amadan。我会(与 eslint 开发人员)争辩说,该规则不应该适用于将数组值分配给像 this.message = res.response.data.errors[0]; 这样的对象属性的情况。除非你能... 你可以。 [foo.bar] = [1](quux: foo.baz = quux: 2) 都可以工作。 哦,太棒了!这些天对 es6 非常流利,但不知道。不错。【参考方案4】:

除了给定的destructuring assignments,如果您想获取某些元素,例如数组的第 11 个和第 15 个元素,您可以对数组进行对象解构。

在这种情况下,您需要使用带有新变量名的object property assignment pattern [YDKJS: ES6 & Beyond],因为您不能将变量作为数字。

var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
     11: a, 15: b  = array;

console.log(a, b);

【讨论】:

【参考方案5】:

解构是一种从存储在(可能是嵌套的)对象和数组中的数据中提取多个值的方法。它可以用于接收数据的位置或作为对象的值。我们将通过一些示例来说明如何使用解构:

数组解构

数组解构适用于所有可迭代值

const iterable = ['a', 'b'];
const [x, y] = iterable;
// x = 'a'; y = 'b'

解构有助于处理返回值

const [all, year, month, day] =
/^(\d\d\d\d)-(\d\d)-(\d\d)$/
.exec('2999-12-31');

对象解构

const obj =  first: 'Jane', last: 'Doe' ;
const first: f, last: l = obj;
// f = 'Jane'; l = 'Doe'

// prop is short for prop: prop
const first, last = obj;
// first = 'Jane'; last = 'Doe'

解构的使用示例

// Variable declarations:
const [x] = ['a'];
let [x] = ['a'];
var [x] = ['a'];

// Assignments:
[x] = ['a'];

// Parameter definitions:
function f([x])  ··· 
f(['a']);


// OR USE IT IN A FOR-OF loop



const arr = ['a', 'b'];
for (const [index, element] of arr.entries()) 
    console.log(index, element);

// Output:
// 0 a
// 1 b

解构模式

任何解构都涉及两方

    解构源:要解构的数据,例如解构赋值的右侧。 解构目标:用于解构的模式。例如解构赋值的左侧。

解构目标是以下三种模式之一:

    赋值目标:通常赋值目标是一个变量。但是在解构赋值中你有更多的选择。 (例如 x) 对象模式:对象模式的部分是属性,属性值又是模式(递归)(例如 first: «pattern», last: «pattern» ) 阵列模式:阵列模式的部分是元素,元素又是模式(例如 [ «pattern», «pattern» ])

这意味着您可以任意深度地嵌套模式:

const obj =  a: [ foo: 123, bar: 'abc' , ], b: true ;
const  a: [foo: f]  = obj; // f = 123

**模式如何访问值的内部? **

对象模式在访问属性之前强制解构源到对象。这意味着它适用于原始值。对对象的强制是使用 ToObject() 执行的,它将原始值转换为包装对象,并使对象保持不变。 Undefined 或 Null 遇到时会抛出类型错误。可以使用空对象模式来检查一个值是否可以强制转换为一个对象,如下所示:

( = [true, false]); // OK, Arrays are coercible to objects
( = 'abc'); // OK, strings are coercible to objects

( = undefined); // TypeError
( = null); // TypeError

数组解构使用迭代器来获取源的元素。因此,您可以对任何可迭代的值进行数组解构。

例子:

// Strings are iterable:
const [x,...y] = 'abc'; // x='a'; y=['b', 'c']


// set value indices
const [x,y] = new Set(['a', 'b']); // x='a'; y='b’;

一个值是可迭代的,如果它有一个键是返回一个对象的symbol.iterator方法。如果要解构的值不可迭代,则数组解构会引发 TypeError

例子:

let x;
[x] = [true, false]; // OK, Arrays are iterable
[x] = 'abc'; // OK, strings are iterable
[x] =  * [Symbol.iterator]()  yield 1  ; // OK, iterable

[x] = ; // TypeError, empty objects are not iterable
[x] = undefined; // TypeError, not iterable
[x] = null; // TypeError, not iterable


// TypeError is thrown even before accessing elements of the iterable which means you can use empty Array pattern [] to check if value is iterable
[] = ; // TypeError, empty objects are not iterable
[] = undefined; // TypeError, not iterable
[] = null; // TypeError, not iterable

可以设置默认值

默认值可以设置为后备

例子:

const [x=3, y] = []; // x = 3; y = undefined

未定义触发默认值

【讨论】:

以上是关于JavaScript 中的数组解构的主要内容,如果未能解决你的问题,请参考以下文章

javascript学习系列(23):数组中的解构方法

javascript中的解构赋值

JavaScript ES6 - 解构赋值

JavaScript ES6 - 解构赋值

JavaScript ES6 - 解构赋值

JavaScript 学习-15.解构赋值