为什么JavaScript没有最后一种方法?[关闭]


124

有点奇怪的是,JavaScript Array类没有提供last方法来检索数组的last元素。我知道解决方案很简单(Ar [Ar.length-1]),但是,这仍然太常用了。

尚未合并的任何严重原因?


39
如果您不介意将数组作为副作用进行更改(例如,无论如何数组都只是临时的),习惯用法就是item= array.pop();
bobince 2010年

7
这是许多上述方法的性能基准:jsperf.com/get-last-item-from-array
Web_Designer 2013年

5
天哪,看着那PERF页面后,出现array[array.length-1]方式比别人快。
约恩德尔姆

@JondIm,但是如果您在函数中创建数组,则需要为其创建一个本地名称(这将导致诸如arr2之类的名称),并且您将使用两行代码而不是oneliner
Danubian Sailor

1
(Ar[Ar.length-1])为我带来20倍的性能提升。
Evgeni Sergeev

Answers:


38

因为Javascript的变化非常缓慢。那是因为人们缓慢地升级浏览器。

许多Javascript库都实现了自己的last()功能。用一个!


20
至少,您可能需要考虑建议一个提供实施的库。例如,Underscore.js是一个不错的选择。参见documentcloud.github.com/underscore/#last
肖恩·林奇

11
@Sean-我认为我不建议在原始海报上推荐特定的Javascript库。Google在评估网络对使用哪个库的集体意见方面做得很好。我为什么要建议一个?的确,为什么您推荐了underscore.js,乍一看对我来说似乎很适合本月?
三联画

6
实际上,我更喜欢下面在库外部实现功能的答案。就是说,当有人通过Google偶然发现此问题时,我建议最重要的答案是帮助其他人继续搜索解决方案,而不是将其发送到后退按钮。
肖恩·林奇

5
问题是“为什么不将此功能内置到Javascript中”而不是“如何实现此功能”。没有理由认为原始作者正在寻找如何实际编写自己的last()函数。问题是关于Javascript核心语言本身的开发性质。
三联画

3
但是,如果@Nikhil想知道如何实现它-下划线有一个很好的注释源。last()的这种实现非常健壮,可能比作者需要的更多,但对于库来说很棒。documentcloud.github.com/underscore/docs/...
reconbot

264

您可以执行以下操作:

[10, 20, 30, 40].slice(-1)[0]

可以添加到一种语言的辅助方法的数量是无限的。我想他们只是没有考虑添加此内容。


11
试图为“接近无限”投下反对票
Triptych

11
为什么?你可以接近你想要的,没有限制:)
阿尔瓦罗·冈萨雷斯

35
这应该是答案。
GiampaoloRodolà2011年

7
@UpTheCreek,因为您不需要将数组存储到变量。
rmobis

5
@ÁlvaroG.Vicario这对于引用数组很合适,但是在您的示例中,您正在使用数字。根据MDN文档:“切片将字符串和数字复制到新数组中。更改一个数组中的字符串或数字不会影响另一个数组。” 如果开发人员想要获取引用“ array.last”以便对其原始数组中的最后一个元素的值进行处理,并且数组值恰好是字符串或数字文字,则此方法将不起作用。
1nfiniti

82

自己定义很容易。这就是JavaScript的力量。

if(!Array.prototype.last) {
    Array.prototype.last = function() {
        return this[this.length - 1];
    }
}

var arr = [1, 2, 5];
arr.last(); // 5

但是,这可能会导致第三方代码出现问题,该第三方代码(错误地)使用for..in循环遍历数组。

但是,如果您不受浏览器支持问题的束缚,则可以通过使函数不可枚举来使用新的ES5语法定义属性来解决该问题,如下所示:

Object.defineProperty(Array.prototype, 'last', {
    enumerable: false,
    configurable: true,
    get: function() {
        return this[this.length - 1];
    },
    set: undefined
});

var arr = [1, 2, 5];
arr.last; // 5

11
请注意,将属性添加到Array的原型可能会破坏代码,其中for..in用于迭代数组。使用for..in迭代数组是一种不好的做法,但是通常这样做足以使更改Array的原型也是一种不好的做法。通常,如果您的脚本需要使用其他未知代码,则不应更改对象,数组,字符串,数字,布尔值和日期的原型。
Dagg Nabbit 2010年

7
@no-感谢您的提示。我应该提到,将枚举性设置为false的ES5语法添加的原因正是为了解决该for..in问题。当然,我们还没有广泛使用ES5,但是现在已经足够了解,因为浏览器正在迅速赶上它,包括IE9。
阿努拉格

4
对于空列表,this.length - 1求值为-1,因为它是一个负数,所以被视为数组属性,而不是元素索引。
粘土化

26

i = [].concat(loves).pop(); //corn

图标猫喜欢爆米花


15
警告:这会创建整个列表的副本,仅弹出一个元素。在时间和空间上都可能非常浪费。不要这样
三联画


5
Array.prototype.last = Array.prototype.last || function() {
    var l = this.length;
    return this[l-1];
}

x = [1,2];
alert( x.last() )

[] .last()的适当输出应该是什么?null还是undefined
阿尔瓦罗·冈萨雷斯

1
可能未定义以使其在语言方面保持一致。
meder omuraliev

null我认为-因为您确实定义了一个数组-只是其中没有有效的对象。仅当在调用的容器上未定义最后一个“属性”时,才应使用undefined。
Nikhil Garg 2010年

3
只需返回this[l-1]就可以undefined正常访问不存在的属性。就个人而言,我宁愿JS抛出异常而不是返回undefined,但是JS更喜欢清除错误。
bobince 2010年

4

来到这里自己寻找这个问题的答案。切片答案可能是最好的,但是我继续创建了一个“最后一个”功能,只是为了练习扩展原型,所以我想我会继续分享。与其他一些功能相比,它具有更多的好处,它使您可以选择在数组中倒数,然后取出倒数第二个或倒数第三个。如果不指定计数,则默认为1,然后取出最后一项。

Array.prototype.last = Array.prototype.last || function(count) {
    count = count || 1;
    var length = this.length;
    if (count <= length) {
        return this[length - count];
    } else {
        return null;
    }
};

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.last(); // returns 9
arr.last(4); // returns 6
arr.last(9); // returns 1
arr.last(10); // returns null

当您使用last(4)或时,last(9)您会失去函数名称的含义,即;last
Prashanth Shyamprasad 2014年

3

这是切片最后一个元素的另一种简单方法

 var tags = [1, 2, 3, "foo", "bar", "foobar", "barfoo"];
 var lastObj = tags.slice(-1);

lastObj现在["barfoo"]

Python以相同的方式进行操作,当我尝试使用JS时,效果很好。我猜脚本语言中的字符串操作以相同的方式工作。

同样,如果您想要数组中的最后两个对象,

var lastTwoObj = tags.slice(-2)

会给你["foobar", "barfoo"]等等。


@Jakub谢谢您的编辑。我错过了关键的负面信号。
普拉桑

不,lastObj将包含["barfoo"]。无论如何,为什么我会做Array.prototype.slice.call(tags而不仅仅是tags.slice


-1

是的,或者只是:

var arr = [1, 2, 5];
arr.reverse()[0]

如果您需要值,而不是新列表。


10
不确定,但这似乎很慢
Jonathan Azulay 2013年

3
除了速度慢之外,它还具有令人讨厌的副作用,因为原始阵列被颠倒了。
史蒂芬·泉
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.