解构以获取es6中数组的最后一个元素


116

在coffeescript中,这很简单:

coffee> a = ['a', 'b', 'program']
[ 'a', 'b', 'program' ]
coffee> [_..., b] = a
[ 'a', 'b', 'program' ]
coffee> b
'program'

es6是否允许类似的东西?

> const [, b] = [1, 2, 3]                              
'use strict'                                           
> b  // it got the second element, not the last one!                      
2                                                      
> const [...butLast, last] = [1, 2, 3]          
SyntaxError: repl: Unexpected token (1:17)                                                                                                                                                        
> 1 | const [...butLast, last] = [1, 2, 3]                                                                                                                                                        
    |                  ^                                                                                                                                                                          
    at Parser.pp.raise (C:\Users\user\AppData\Roaming\npm\node_modules\babel\node_modules\babel-core\node_modules\babylon\lib\parser\location.js:24:13)                                           

我当然可以用es5方法做到这一点-

const a = b[b.length - 1]

但这也许有点容易出错。摔得痛只能是重组中的最后一件事吗?


7
为什么每个人都认为ES6会改变一切,并且有一些执行xyz的新语法?
菲利克斯·克林

23
@FelixKling,问题特别是关于...es6中的行为的,尤其是它只能在解构时或在参数列表中用作最后用途。这对于从coffeescript进入es6的人来说可能是违反直觉的,因此此问题可能很有用。
乔治·西姆斯

这意味着,除了[1,2,3].slice(-1)您,您甚至无法破坏相当于的结构[1,2,3].slice(0, -1)。这些是常见的操作。ES6的破坏性在某种程度上是个玩笑!
scriptum

@即使有正当的理由-处理无限的可迭代对象。
乔治·西姆斯

休息太糟糕,因为第一个参数不起作用。本来很酷...这是一个使用一些答案的jsperf jsperf.com/destructure-last/1
Shanimal

Answers:


46

在ES6 / 2015中是不可能的。该标准只是没有提供它。

正如您在规范中所看到FormalParameterList可以是:

  • 一个 FunctionRestParameter
  • 一个FormalsList(参数列表)
  • a FormalsList,然后是aFunctionRestParameter

说完FunctionRestParameter之后参数没有设置。


215

console.log('last', [1, 3, 4, 5].slice(-1));
console.log('second_to_last', [1, 3, 4, 5].slice(-2));


4
不错的简单非变异解决方案。
杰克·斯蒸汽

1
@Shanimal Depends,我得到的pop版本更快(OS X,Chrome 68)。
戴夫·牛顿

1
@Dave Newton但是pop()导致突变
Antonio Pantano

1
@AntonioPantano是的,它使副本变异。关键是没有给出是否更快。
戴夫牛顿

53

我相信ES6至少可以帮助您:

[...arr].pop()

给定您的数组(arr)不是未定义的并且是一个可迭代的元素(是的,甚至字符串都可以使用!),它应该返回最后一个元素。即使对于空数组,它也不会改变。它虽然创建了一个中间数组,但是应该不会花费太多。

您的示例将如下所示:

  console.log(  [...['a', 'b', 'program']].pop() );


6
嗯,这很糟糕,甚至.slice(-1)[0]还差一点,或者var [last]=arr.slice().reverse()如果您需要的话,它是另一个丑陋的
-caub

6
我以为这篇文章是关于ES6 / ES2015的,不是吗?但是我特别喜欢你的最后一块。如何将两者结合起来:var [last] = arr.slice(-1);)
shoeel

13
我最喜欢的方式是Object.defineProperty(Array.prototype, -1, { get() {return this[this.length - 1] } }); [1,2,3][-1]
caub

3
尽管这可行,但它是可变的,可以从原始数组中删除该项目。在许多情况下都不理想。
GavKilbride

4
@GavKilbride它没有。示例[].concat(arr).pop();和不变异的例子相同arr

37

您可以对反向数组进行解构,使其接近所需的数组。

const [a, ...rest] = ['a', 'b', 'program'].reverse();
  
document.body.innerHTML = 
    "<pre>"
    + "a: " + JSON.stringify(a) + "\n\n"
    + "rest: " + JSON.stringify(rest.reverse())
    + "</pre>";


2
聪明。比const last = ['bbb', 'uuu', 'iii'].slice(-1);?在表演方面?
Vadorequest

1
.slice(-1)技术上讲,它比较快,但是一次调用不会同时提供最后一项和子数组,这是...解构时使用splat 的好处。当在更长的数组上使用时,可以考虑两次反转带来的性能下降,但是对于一个小的脚本来说,可能值得这样做吗?但是,let a = array.slice(-1), rest = array.slice(0,array.length-2)如果您仍然希望在ES5中使用oneliner,也可以轻松地实现这一目标,即快约4%。jsperf.com/last-array-splat
mix3d

17

另一种方法是:

const arr = [1, 2, 3, 4, 5]
const { length, [length - 1]: last } = arr; //should be 5
console.log(last)


1
@isakbob yeap,您在这里
Den Kerny

很难阅读,或者也许只是我的大脑
webjay

使用多个道具可能会很有帮助,所以,是的,只是你的,xd xd xd
Den Kerny

5

不一定是最高效的方式。但是根据上下文,一种相当优雅的方式是:

const myArray = ['one', 'two', 'three'];
const theOneIWant = [...myArray].pop();

console.log(theOneIWant); // 'three'
console.log(myArray.length); //3


3
我看不到此解决方案有什么优雅之处,但是无论如何@shoesel已经发布了它
Bergi

2

const arr = ['a', 'b', 'c']; // => [ 'a', 'b', 'c' ]

const {
  [arr.length - 1]: last
} = arr;

console.log(last); // => 'c'


2
是的,在进行其他销毁时,我发现它很有用。就其本身而言,它不像经典解决方案那样容易阅读。
andrhamm


1

您可以尝试以下技巧:

let a = ['a', 'b', 'program'];
let [last] = a.reverse();
a.reverse();
console.log(last);

0

肯定地,问题是关于 解构的JavaScript数组,我们知道这是不可能通过使用解构赋值有一个数组的最后一个项目,是有办法做到这一点不变,看到以下内容:

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

~~~
const arrDepth = arr.length - 1;

const allExceptTheLast = arr.filter( (dep, index) => index !== arrDepth && dep );
const [ theLastItem ] = arr.filter( (dep, index) => index === arrDepth && dep );

我们不对arr变量进行突变,但除最后一项外,其余所有数组成员均作为数组,并且最后一项单独存在。



0

不破坏方式,但可以帮助。根据javascript文档和反向方法,可以尝试以下方法:

const reversed = array1.reverse();
let last_item = reversed[0]
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.