2376

我需要在数组的开头添加或预置元素。

例如,如果我的数组如下所示:

[23, 45, 12, 67]

我的AJAX电话的回应是34,我希望更新后的数组如下所示:

[34, 23, 45, 12, 67]

目前我计划这样做:

var newArray=[];newArray.push(响应);for(var i=0;i<theArray.length;i++){newArray.push(theArray[i]);}theArray=newArray;删除newArray;

有更好的方法吗?JavaScript有什么内置的功能可以做到这一点吗?

我的方法的复杂性是O(n)看到更好的实现会非常有趣。

  • 27
    仅供参考:如果需要在数组的开头连续插入一个元素,使用起来会更快语句后跟对的调用颠倒,而不是呼叫取消移位总是。 评论 2018年2月15日8:56
  • @Jenny O'Reilly你应该把这个作为答案。与我的用法完全匹配。谢谢
    – 抢劫
    评论 2018年6月7日12:19
  • 2
    性能测试:jsperf.com/adding-element到阵列启动但每个浏览器的结果都不同。 评论 2019年4月23日18:34

12个答案12

重置为默认值
3967

使用取消移位.就像,但它将元素添加到数组的开头而不是末尾。

  • 取消移位/-将元素添加到数组的开头/结尾
  • 转移/流行音乐-删除并返回数组的第一个/最后一个元素

一个简单的图表。。。

unshift->[array]<-push移位<-[array]->pop

和图表:

  添加 去除 开始 结束
X(X) X(X)
流行音乐 X(X) X(X)
取消移位 X(X) X(X)
转移 X(X) X(X)

查看MDN阵列文档。实际上,每种能够从数组中推送/弹出元素的语言也都能够取消移位/移位(有时称为前推(_F)/pop_前)元素,您永远不应该自己实现这些。


正如注释中所指出的,如果要避免更改原始数组,可以使用凹入,它将两个或多个数组连接在一起。您可以使用此功能将单个元素推送到现有数组的前面或后面;为此,您需要将新元素转换为单个元素数组:

常量数组=[3,2,1]const newFirstElement=4const newArray=[newFirstElement].concat(数组)//[4,3,2,1]console.log(newArray);

凹入也可以附加项目。的参数凹入可以是任何类型;如果它们还不是数组,则隐式包装在单个元素数组中:

常量数组=[3,2,1]const newLastElement=0//这两条线是等效的:const newArray1=array.concat(newLastElement)//[3,2,1,0]const newArray2=array.concat([newLastElement])//[3,2,1,0]console.log(newArray1);console.log(newArray2);

2
  • 70
    使用凹入可能更可取,因为它会返回新数组。对于链接非常有用。[thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)等…如果您使用取消移位,你不能这样做,因为你得到的只是长度。
    – 用户5900250
    评论 2016年9月23日18:27
  • 12
    移动/取消移动、推/弹出、拼接。这些方法的名称非常合理。 评论 2018年4月25日12:32
1744

阵列操作图像

变量a=[23,45,12,67];a.卸载(34);控制台.log(a);//[34, 23, 45, 12, 67]

5
  • 204
    人们之所以需要4个日常使用的函数的可视化指南,是因为它们的函数名是加密的。。。为什么取消移位不称为插入?Shift应为Remove。等。。。
    – 帕斯卡
    评论 2013年6月29日21:24
  • 100
    //为什么取消移位不称为插入//它来自C编程语言的约定,其中数组元素被视为堆栈。(请参见perlmonks.org/?节点id=613129完整解释) 评论 2013年7月26日21:05
  • 43
    @Pascal不,插入和删除将是特别糟糕的名称;它们意味着随机访问,而不是从数组前面添加/删除
    – 用户229044
    评论 2013年10月22日13:06
  • 33
    我本以为unshift应该删除第一个键,shift将插入第一个键中,但这只是我的一般想法 评论 2014年9月25日1:50
  • 7
    请注意[23、45、12、67].取消移位(34)行不通。阵列必须首先保存在变量中,因为取消移位 它本身返回一个值。 评论 2017年3月15日15:12
367

对于ES6,使用排列运算符...:

演示

var arr=[23,45,12,67];arr=[34,…arr];//结果:[34,23,45,12,67]控制台.log(arr)

6
  • 34
    还创建了一个新数组,用于纯函数
    – 德文吉
    评论 2017年8月8日19:01
  • 1
    这里的性能含义是什么?它比使用unshift()慢吗? 评论 2018年3月2日9:49
  • 1
    当然,它会变慢,因为它是一个不可变数组(创建一个新数组)。如果您使用的是大阵列,或者性能是您的首要要求,请考虑使用凹入而不是。 评论 2018年3月2日15:42
  • 1
    @AbdennourTOUMI只是为了澄清你的评论。它不是在创建一个不可变的数组,它只是在不改变现有数组的情况下创建一个新数组。
    – 弗利姆
    评论 2021年11月11日11:38
  • 1
    @堆栈保存课程2018年(2022年),业绩至关重要。它在您的todo应用程序或20个元素的网络商店UI中可能并不重要,但在我的500 MB类型数组的图形编辑器中,它很重要。 评论 2022年11月7日15:00
95

另一种方法是通过凹入:

var arr=[1,2,3,4,5,6,7];控制台.log([0].concat(arr));

两者之间的差异凹入取消移位是那个吗凹入返回一个新数组。可以找到他们之间的表现在这里.

函数fn_unshift(){arr.unshift(0);返回arr;}函数fn_concat_init(){返回[0].concat(arr)}

测试结果如下:

在此处输入图像描述

5
  • 除了添加引用之外,您的答案最好附加这两者的性能比较。 评论 2016年6月15日9:12
  • 我刚得到在我们发布v2的过程中,jsPerf暂时不可用。请稍后再试从链接。另一个很好的理由是要包含结果而不是链接到结果。
    – 跳跳虎
    评论 2016年8月21日1:00
  • jsPref(jsPref)结果:取消移位:25510±3.18%慢99%凹入:2436894±3.39%最快
    – 照明器
    评论 2016年11月3日10:28
  • 在最新的Safari中,fn_unshift()跑得更快。
    – 帕萨特
    评论 2017年7月21日13:22
  • 在最新的Safari(v 10)中,fn_unshift()再次变慢。
    – rmc哈里
    评论 2017年11月9日11:22
53

快速备忘单:

术语shift/unshift和push/pop可能有点令人困惑,至少对不熟悉C语言编程的人来说是这样。

如果你不熟悉这个行话,下面是其他术语的快速翻译,可能更容易记住:

*array_unshift()-(也称为前置;;插入之前;;插入开始)*array_shift()-(aka UnPrepend;;RemoveBefore;;Remove From Begin)*array_push()-(又名Append;;InsertAfter;;Insert AtEnd)*array_pop()-(aka UnAppend;;RemoveAfter;;Remove FromEnd)
39

使用ES6破坏(避免改变原始数组):

const newArr=[项目,…oldArr]

1
27

您有一个数组:var arr=[23,45,12,67];

要将项目添加到开头,您需要使用剪接:

var arr=[23,45,12,67];棱角拼接(0,0,34)console.log(arr);

4
  • 排列重复(0,排列长度,34); 评论 2015年10月15日20:08
  • 1
    @LiorElrom你的片段是做什么的? 评论 2016年6月22日11:31
  • @它是浏览器特有的,在Firefox 54中是取消移位速度提高50%(但大多更具可读性)
    – 尤拉伊
    评论 2017年5月17日7:16
  • @撅嘴不再。速度慢得多。
    – 安得烈
    评论 2019年9月12日16:15
26

无突变

实际上,所有取消移位/转移/流行音乐 突变源数组。

这个取消移位/从开始/结束向现有数组添加一个项,然后转移/流行音乐从数组的开头/结尾删除一项。

但是,没有什么方法可以在不发生突变的情况下向数组中添加项。结果是一个新数组,添加到数组末尾使用以下代码:

const originArray=['one','two','three'];const newItem=4;const newArray=originArray.concat(newItem);//欧洲标准5const newArray2=[…originArray,newItem];//欧洲标准6+

要添加到原始数组的开头,请使用以下代码:

const originArray=[一个,两个,三个];const newItem=0;const newArray=(originArray.slice().reverse().concat(newItem)).revverse();//欧洲标准5const newArray2=[新项,…originArray];//欧洲标准6+

通过上面的方法,您可以添加到一个数组的开始/结束,而不会发生突变。

  • 我刚放了一个函数的末尾originArray(原始阵列)以防止其发生变化。 评论 2019年12月4日7:34
  • 1
    令人惊叹的!当涉及到(Redux)状态管理时。。。这个答案很宝贵! 评论 2020年2月23日13:16
  • [newItem,…originArray];//ES6+语法很棒!干得很好!!谢谢。
    – 蝙蝠
    评论 2021年10月13日7:28
19

在数组中预置新元素的备忘单

1数组#取消移位

常数列表=[23,45,12,67];list.unshift(34);console.log(列表);//[34, 23, 45, 12, 67];

2阵列#拼接

常数列表=[23,45,12,67];列表拼接(0、0、34);console.log(列表);//[34, 23, 45, 12, 67];

三。ES6传播。。。

常数列表=[23,45,12,67];const newList=[34,…list];console.log(newList);//[34, 23, 45, 12, 67];

4数组#concat

常数列表=[23,45,12,67];const newList=[32].concat(列表);console.log(newList);//[34, 23, 45, 12, 67];

注:在这些示例中,您可以通过提供更多要插入的项来预先插入多个项。

10

如果需要在数组的开头连续插入一个元素,使用它会更快语句后跟对的调用颠倒,而不是呼叫取消移位总是。

基准测试: http://jsben.ch/kLIYf

  • 2
    注意:初始数组应为空。
    – 192kb
    评论 2019年8月15日10:12
  • 2021年,您的基准显示取消移位跨所有主要桌面浏览器(至少在Mac上)。 评论 2021年7月7日21:52
  • @OllyHodgson使用Firefox在Ubuntu Linux上进行测试:反向解决方案速度快3倍。 评论 2021年11月6日10:22
8

使用剪接我们在数组的开头插入一个元素:

arrName.splice(0,0,'newName1');
0
8

如果要在数组的开头推送数组中的元素,请使用<func>.apply(<this>,<Array of args>):

常数arr=[1,2];arr.unshift.apply(arr,[3,4]);console.log(arr);//[3, 4, 1, 2]

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.