这是我目前为止的javascript代码:
1 2 3 4
| var linkElement = document.getElementById("BackButton");
var loc_array = document.location.href.split('/');
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2])));
linkElement.appendChild(newT); |
当前,它需要从URL获取数组中的第二个到最后一个项。但是,我想检查数组中最后一个项是否为"index.html",如果是,则改为抓取第三个到最后一个项。
1 2 3 4 5
| if(loc_array[loc_array.length-1] == 'index.html'){
//do something
}else{
//something else.
} |
如果您的服务器为"index.html"和"index.html"提供相同的文件,您也可以使用:.toLowerCase()。
不过,如果可能的话,您可能会考虑使用服务器端:它将更干净,并且适用于没有JS的人。
- "为没有JS的人工作"-我…我不明白。
- 一些奇怪的人实际上在他们的浏览器中禁用了javascript。我知道这很令人震惊。
- 这将复制变量名或创建非标准函数。
- loc_数组来自document.location.href(请参见op)。我不知道你会怎么把它传输到服务器上,这样它就可以在不使用JavaScript的情况下被处理掉(尽管我确定有办法)。我认为,在这种情况下,您可能会把那些禁用JS的用户抛在脑后,或者想出一种比实际情况复杂得多的方法。另一方面,如果您在生成页面时知道页面的URL,那么服务器端代码当然可以在呈现页面之前轻松地做到这一点。
- 我们都能同意如果一个用户禁用了javascript,那么他们还是会被搞得一团糟吗?不要为了支持奇异的不可能发生的场景而牺牲应用程序的设计和效率。
- 我在这里感觉到一些误解——我非常肯定"people without js"评论是关于文件名中使用的大小写,而不是JS本身的问题。
- 你不认为99.9%禁用JS的"用户"实际上是从HTML中获取数据的僵尸吗?或者开发人员"测试",如果您的站点不使用JS?
- 我们能不能都同意,许多web开发人员没有礼貌,包括所有不需要的bloat脚本,比如跟踪,这是完全禁用随机不可信网站上的js的一个非常有效的原因?这并不像有些人想象的那样不太可能。如果你重视隐私的话,这实际上是明智的行为方式。
- 我同意Zelphir的观点。页面上充斥着javascript,这通常会增加加载时间、数据消耗和复杂性。除此之外,还有不同的跟踪器可以在彼此之间共享数据,一般来说,想要禁用javascript而不是阻塞特定的脚本是很合理的。上述脚本还用于检查是否加载了其他(如广告)脚本,然后给您一个大的停止标志,声称"我们需要广告来维持我们自己"。我们也忘记了你不应该信任客户。
- 你不能像Python那样做吗?,slice只返回数组而不是整数
- 我同意@dragas的观点,同时也希望指出,任何通过javascript发布广告的人都只是在打开您的网站,让跨域的胡说八道滥用您的网站。下拉ADS服务器端,确保它们是干净的,然后从服务器托管。(更不用说这样就可以阻止大多数的adblocker了。)
- "为什么禁用JS"讨论真的属于这里吗??
- 虽然原则上我同意Philipp的观点,即Javascript讨论并不真正属于这里,但在一个关于如何在Javascript中实现某些东西的问题的公认答案中提到了这一点。我也同意Devios的观点,因为你的用户不太可能不启用它,而且对于一个基本概念的问题(不不不尊重操作-我在这里查找),答案中确实不需要提到它。
- @Zelphir"网络开发人员没有礼貌"——很少是网络开发人员,而是业务经理。
不确定是否有缺点,但这看起来很简洁:
。
或
。
如果数组为空,两者都将返回undefined。
- 这样做的好处是简洁,而不是像.pop()那样改变输入。
- 这可能会稍微降低效率,这取决于切片是如何写入的。slice()创建了一个新的数组,在本例中,只使用最后一个元素,只是为了访问最后一个元素,所以您将有一些额外的内存分配(这需要有限的时间)。
- @但是,性能开销将是最小的。中间数组只有一个元素长。只要你不用打这个电话一百万次,你就没事了。
- 考虑到速度问题:@user1941782做了一个微基准。slice()可以在新计算机上每秒运行大约1000万次。使用[len-1]的速度快了约1000倍,但这两种方法的速度都很快,可能不会成为限制因素;因此,imho不必为使用slice()而感到难过。
- 很适合在执行类似于windows.location.pathname.split('/').slice(-1)[0]的操作时避免需要中间变量,这样就可以在上面调用len,因为javascript不像某些语言那样将[-1]理解为数组的最后一个元素。
- 我看到早熟的优化团队正在形成。
- (/thingihavetomatch(thingiwant)/.exec(strvar)[未定义]).slice(-1)[0]适用于正则表达式;)
- 如果JS也可以执行[-1], [-2]等操作,那就太好了。它很方便
- 不管怎样,只要可能,window.location.pathname.split('/').pop()看起来就更好了。
- 使用破坏也很好:const [lastItem] = arr.slice(-1)。
使用array.pop:
1
| var lastItem = anArray.pop(); |
重要提示:这将返回最后一个元素并将其从数组中移除
- 这是可行的,但它会从数组中删除该项,而这不是OP所要求的。
- 我喜欢在我不想存储在变量中的废弃列表中使用这个:var last = path.split('/').pop();很高兴这个答案在这里!
- 手术室说,"如果是这样的话,把第三个换成最后一个。"如果你弹出,第三个到最后一个不再是第三个到最后一个。.pop()确实"获取"了最后一项。不过,我完全同意,最好在答案本身中提到这种方法修改了数组。
@chaigoy发布的内容的较短版本:
1 2 3
| Array.prototype.last = function() {
return this[this.length - 1];
} |
。
读取-1索引将返回undefined。
编辑:
如今,首选项似乎是使用模块,并避免接触原型或使用全局命名空间。
1 2 3
| export function last(array) {
return array[array.length - 1];
} |
- 我把它叫做peek,当使用类似于堆栈的数组时,它类似于pop。
- 如果不清楚这是如何实际使用的,这里有一个例子:var lastItem = [3,2,1,5].last();。lastItem的值为5。
- 这个答案是正确的,也很干净,但是(!!!!)使用javascript的经验法则是Do NOT modify objects you Do NOT own。这很危险,因为有很多原因,比如1。在您的团队中工作的其他开发人员可能会感到困惑,因为此方法不是标准的2。对于库中的任何更新,甚至使用更低或更高版本的ecmascript,它都很容易丢失!
- 我非常喜欢这个解决方案,但是-按照@farzadyz的评论-w3schools.com/js/js_object_prototypes.asp声明:只修改您自己的原型。不要修改标准JavaScript对象的原型。
- @Farzadyz——任何定制原型丢失的风险都很低。我十年来从未遇到过。另外,我反对它混淆了其他开发人员,因为您可以很容易地在您的IDE中跟踪方法的来源,如果这还不够,您可以始终为您的自定义原型方法(例如使用_)加前缀,并且这肯定不会混淆项目中涉及的任何人,除非他们没有正确地介绍给高级开发人员的项目。我相信,多年后,扩展原始原型是完全可以的。在团队中工作时从未遇到过问题。
- @垂直同步对于中级或高级开发人员,你可能是对的,但是初级开发人员很容易被混淆,事实上这不是一个争论的话题。这要看情况而定。所以我可以说,你是对的
- 这真的应该是JS中数组的标准方法
- 对于任何想知道的人,这会破坏array.foreach()。我仍然同意修改原型并不是最糟糕的事情,但这件事很糟糕。
- 如何中断array.foreach()?因为我试过了,没有看到任何东西坏了…
- 在我看来,修改Array.prototype没有什么大问题,但是你应该使用Object.assign(Array.prototype, 'last', { value: function () { … } });。否则,该属性将是可枚举的。
- 停止建议修改原型。有人提议将此属性添加到javascript中,由于此代码,因此不能将其添加到.last下以避免"Web兼容性问题"。你为什么要这么固执?"我从来没有遇到过"这不是一个好借口。
- @最近,首选似乎是使用模块,避免接触原型或全局命名空间。这个答案是6岁了,事情有了一些变化。我会在答案里写个便条。
有两种选择:
1
| var last = arr[arr.length - 1] |
号
或
1
| var last = arr.slice(-1)[0] |
号
前者更快,但后者看起来更好
http://jspef.com/slice-vs-length-1-arr
- 从总体性能来看,var last = arr[arr.length - 1]是该线程中最好的答案。
- 后者返回一个数组。
- arr.length-1可能快150-200倍,但当最慢的方法的速度已经达到每秒数百万次操作的速度时,我认为99.99%的情况下(甚至当slice/pop允许您提取数组中未保存在变量中的最后一个元素时,为了代码美观的目的,性能不是主要的问题)
- 对于非JS熟悉的程序员来说,arr.slice(-1)[0]并不清楚。arr[arr.length - 1]更清晰,更容易"猜测"程序员的想法:)
- arr[arr.length-1]是最清晰、最快的
以下是如何在不影响原始数组的情况下获得它
1 2
| a = [1,2,5,6,1,874,98,"abc"];
a.length; //returns 8 elements |
号
如果使用pop(),它将修改数组
1 2
| a.pop(); // will return"abc" AND REMOVES IT from the array
a.length; // returns 7 |
号
但是您可以使用它,这样它就不会对原始数组产生影响:
1 2 3
| a.slice(-1).pop(); // will return"abc" won't do modify the array
// because slice creates a new array object
a.length; // returns 8; no modification and you've got you last element |
号
- 应该执行slice(-1.pop(),否则将复制整个数组(实际上只需要复制最后一个元素)。
- 那就不需要那辆车了:只要做那辆车就行了。
"最干净"的ES6方式(IMO)是:
1 2
| const foo = [1,2,3,4];
const bar = [...foo].pop(); |
。
这就避免了foo的变异,就像.pop()如果我们不使用扩散操作符的话会发生的那样。也就是说,我也喜欢foo.slice(-1)[0]解决方案。
- 您还可以使用数组析构函数使其更ES6;)stackoverflow.com/a/46485581/31671
- 请注意,此解决方案执行整个数组的副本。
- 它和.slice(-1)[0]一样不可读,但速度较慢。也可以使用EDOCX1[2]
- 为了"干净"的语法而复制整个数组对我来说似乎很愚蠢。看起来都不怎么好看
- 所以[…foo]==foo.slice()。理论上两者都可以执行内存复制。但是,如果没有memcopy(调试之外),javascript vm优化器是否会将[…foo].pop()、foo.slice().pop()、foo.slice(-1)[0]和foo.reverse()[0]优化为同一代码?如果不是,纳秒的差异是否真的会导致性能问题?我认为最好不要做微观分析。如果您需要最好的性能,那么就依赖于您的编译/小型化器,如babel或webpack。不要说每个人都是对的。但是这些区别对我来说是空白和标签。从视觉上讲,我有点喜欢这个。
我宁愿使用array.pop()而不是索引。
1 2 3
| while(loc_array.pop()!="index.html"){
}
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length]))); |
这样,您总是可以得到index.html之前的元素(前提是您的数组将独立index.html作为一个项)。注意:不过,您将丢失数组中的最后一个元素。
- 这有点慢,但你可以做loc_array.slice().pop()。
- @然后skizey最好执行loc_array.slice(-1.pop(),只切掉最后一个元素。
使用带负值的切片方法可以得到数组的最后一项。
你可以在下面阅读更多关于它的信息。
1 2 3 4 5
| var fileName = loc_array.slice(-1)[0];
if(fileName.toLowerCase() =="index.html")
{
//your code...
} |
。
使用pop()将更改数组,这并不总是一个好主意。
- 不过,slice返回一个数组,所以使用arr.slice(-1)[0],就像这个答案。
- @Cees Timmerman-谢谢。我修改了密码
- 如果性能是一个问题,那么要知道这个方法比array[array.length - 1]jspef.com/get-last-item-from-array/13慢得多。
我认为,如果您只想在不移除元素的情况下获取元素,那么更简单的做法是:
。
注:如果数组为空(如[],则返回undefined。
顺便说一句。。。我没有检查性能,但我认为写起来更简单更干净
- 注意a)这不会返回最后一个值,而是返回一个带有最后一个元素(arr.slice(-1)[0] === arr[arr.length - 1]的数组),b)由于它将arr复制到一个新数组中,所以速度很慢(有关性能测量,请参阅stackoverflow.com/a/51763533/2733244)。
你可以使用这个模式…
1
| let [last] = arr.slice(-1); |
号
虽然它读起来相当好,但请记住,它创建了一个新的数组,因此比其他解决方案效率更低,但它几乎不会成为应用程序的性能瓶颈。
如果一个人想一次性获得最后一个元素,他/她可以使用Array#splice():
1
| lastElement = document.location.href.split('/').splice(-1,1); |
。
在这里,不需要将拆分的元素存储在数组中,然后到达最后一个元素。如果获取最后一个元素是唯一的目标,那么应该使用它。
注意:这将通过删除其最后一个元素来更改原始数组。把splice(-1,1)看作是弹出最后一个元素的pop()函数。
- 这不是返回数组中的最后一个元素,而不是最后一个元素本身吗?
- @Tozazaburo不是同一件事吗?
- 这将修改数组。可以使用slice(-1)而不是splice(-1)来保持原始数组不变。@阿拉姆科查里安没有,对比一下["hi"]和"hi"。
对于那些不怕重载数组原型的人(对于枚举屏蔽,您不应该这样做):
1 2 3 4 5 6 7 8
| Object.defineProperty( Array.prototype,"getLast", {
enumerable: false,
configurable: false,
writable: false,
value: function() {
return this[ this.length - 1 ];
}
} ); |
- 没有理由假定变量"未定义"未定义。任何人都可以编写类似"var undefined=true;"的代码,从而破坏代码。并且,通过扩展数组,可以使..in循环产生意外的结果。好的程序员知道他们必须检查..在循环中继承的值,但不是每个人都是好的程序员,我们也不会破坏他们的代码。
- 它几乎不会破坏我的代码!你为什么这么认为?如果有人想重新定义未定义,那么就让他们来做,尽管这是一件非常疯狂的事情。这就是JavaScript的威力。如果愿意,他们还可以重新定义array.getlast。另外,优秀的程序员使用object.defineproperty绕过枚举。
- 更新了Object.defineProperty演示使用的答案,并根据@aramkocharyan精简了函数体。
我通常使用下划线,有了它,你就可以
1 2 3
| if (_.last(loc_array) === 'index.html'){
etc...
} |
号
对我来说,这比loc_array.slice(-1)[0]更语义化。
jquery巧妙地解决了这一问题:
1 2 3 4
| > $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined |
号
- 但只有当您已经使用jquery时。加载整个库来做每种支持数组的语言都可以做的事情是疯狂的。
- 负切片并不是许多旧语言中的本地语言,jquery在大多数情况下节省了大量时间,因此这可能是开始使用它的一个很好的借口。
- 如果有许多其他方法可以在不加载整个库的情况下执行相同的操作,但仍然保持兼容,则不会这样做。接受的答案完全没有问题,也可以提取到函数中。
- 重新设计车轮有利于优化,但我更喜欢一个经过良好测试、文档记录良好且高效的解决方案,这已经完成了。
- 如果您不信任该语言本身,那么使用jquery是一个您自欺欺人的谎言。这实际上就是访问数组元素。在许多用例中,我同意您的观点,但这太基本了。同样,如果您已经在您的项目中使用了jquery,那么它完全可以。为了一些像访问数组的最后一个元素那样简单的事情,不值得添加一个完整的、功能强大的库。
- 另外:如果jquery有一个方法$.defineVar = function (scope, name, value) { scope[name] = value; },不管jquery向它抛出多少文档,我还是会使用var foo = 'bar'而不是$.defineVar(window, 'foo', 'bar');。此外,jquery有很好的文档记录,而javascript也是。事实上,它甚至被指定了。你真的不能再详细了。
- 对于第三条评论,我很抱歉,但我刚刚查看了jquery的源代码,它们完全按照接受的答案所建议的方式进行操作。这并不奇怪,但它证明了不需要为此加载jquery。没有浏览器的怪癖来解决问题或类似的事情。
- 这是一种过于轻松的方式,但jquery提供了一个较短的、标准的功能,成本可以忽略不计。
- …而且,Array.prototype.get = function (index) { return (index < 0) ? this[this.length + index] : this[index]; };也没有装载另外10000条线路的成本。我现在就链接到meta.stackexchange.com/questions/45176/&hellip;,停止对此发表评论。
- 这有点危险:stackoverflow.com/questions/8859828/&hellip;
- 这个想法很重要。使用Object.defineProperty或创建Arraysutils类。关键是,如果实现实际上是等效的,那么没有理由选择10000行而不是3行。不要介意你根本不需要定义这个方法。
- 我只是指出了一个原因。jquery已经避免了这个陷阱。
这个问题已经存在很长时间了,所以我很惊讶没有人提到仅仅在pop()之后重新启用最后一个元素。
arr.pop()与arr[arr.length-1]的效率完全相同,并且两者的速度与arr.push()相同。
因此,您可以摆脱:
---编辑[推前检查thePop不是undefined]---
1 2
| let thePop = arr.pop()
thePop && arr.push(thePop) |
号
---结束编辑---
可以降低到这个速度[编辑:但是不安全!))
1
| arr.push(thePop = arr.pop()) //Unsafe if arr empty |
号
这个速度是arr[arr.length-1]的两倍,但是你不必在索引上浪费时间。这在任何一天都是值得的。
我尝试过的解决方案,以及arr[arr.length-1]的执行时间单位(etu)的倍数:
[方法]……
1 2 3 4 5 6 7 8 9 10
| arr[arr.length - 1] ------> 1 -----> 1
let myPop = arr.pop()
arr.push(myPop) ------> 2 -----> 2
arr.slice(-1).pop() ------> 36 -----> 924
arr.slice(-1)[0] ------> 36 -----> 924
[...arr].pop() ------> 120 -----> ~21,000,000 :) |
最后三个选项,尤其是[...arr].pop(),随着阵列大小的增加而变得非常糟糕。在没有我的机器内存限制的机器上,[...arr].pop()可能保持120:1的比例。不过,没有人喜欢资源猪。
- 精彩的回答。与String.split()合作时我需要的
- 如果初始数组可以为空,这种方法将导致错误的结果,并且[]将变为[undefined]。你需要用明确的undefined检查来保护向后推,比如myPop !== undefined && arr.push(myPop)检查。
- 漂亮又有效。
1
| const lastElement = myArray[myArray.length - 1]; |
号
从性能角度来看,这是最佳选择(比arr.slice(-1)快约1000倍)。
- 它是性能方面的最佳解决方案。但就代码质量而言,它并不是最好的。输入var lastelement=arr[arr.length-1];太容易了。
就我个人而言,我会赞成Kuporific/Kritzikratzi的回答。如果使用嵌套数组,array[array.length-1]方法会变得非常难看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var array = [[1,2,3], [4,5,6], [7,8,9]]
?
array.slice(-1)[0]
?
//instead of
?
array[array.length-1]
?
//Much easier to read with nested arrays
?
array.slice(-1)[0].slice(-1)[0]
?
//instead of
?
array[array.length-1][array[array.length-1].length-1] |
号
- 更简单的是一种观点,我不会反对,但是创建一个新的数组实例只为了获取某些项肯定是不明智的。
可以将last()函数添加到Array原型中。
1 2 3
| Array.prototype.last = function () {
return this[this.length - 1];
}; |
号
- 记住,这是一种非常不鼓励的反模式。
- @凯撒索你能解释一下为什么或者提供一个链接吗?
- @Eko24ive简而言之,您正在修改全局对象,这些对象既用于代码中,也用于脚本中的任何其他库中,这很危险。此外,如果将来添加了语言,则会使代码暴露在可能的中断中。过去的一些图书馆做了这件事,对此深表遗憾。了解更多信息:stackoverflow.com/questions/14034180/&hellip;
- 请参阅本页后面的解决方案。解决方案是创建一个包装函数名为"w()",它返回一个具有方法last()的对象,该方法将数组的最后一项作为参数返回给w()。然后,w()在方法last()方面的结果的行为与数组的行为类似,前提是它们的原型被赋予了这个方法。但事实并非如此,您不会破坏任何全局功能。记住,javascript是基于原型的,这意味着每个对象都可以有自己的方法,如果您只需要一个新方法,就不需要破坏原型。
编辑时间:
最近,我又提出了一个解决方案,我认为这是最适合我需要的:
1 2 3 4 5 6 7
| function w(anArray) {
return {
last() {
return anArray [anArray.length - 1];
};
};
} |
号
根据上述定义,我现在可以说:
1 2
| let last = w ([1,2,3]).last();
console.log(last) ; // -> 3 |
号
"w"代表"wrapper"。您可以看到如何轻松地添加更多除"last()"之外的方法。
我说"最适合我的需要",因为这允许我可以很容易地添加其他这样的"助手方法"任何javascript内置类型。什么来了请记住,lisp的car()和cdr()用于实例。
- 第四个是为了好玩和可读性:myArray.reverse()[0]。
- 为什么要用包装纸?如果必须调用w函数,只需使函数返回最后一项。
您可以在Array的原型中添加一个新的属性getter,以便可以通过Array的所有实例访问它。
getter允许您像访问属性值一样访问函数的返回值。函数的返回值当然是数组的最后一个值(this[this.length - 1])。
最后,在检查last属性是否仍然是undefined的条件下包装它(不由可能依赖它的另一个脚本定义)。
1 2 3 4 5 6 7 8 9 10 11 12 13
| if(typeof Array.prototype.last === 'undefined') {
Object.defineProperty(Array.prototype, 'last', {
get : function() {
return this[this.length - 1];
}
});
}
// Now you can access it like
[1, 2, 3].last; // => 3
// or
var test = [50, 1000];
alert(test.last); // Says '1000' |
号
不适用于Ie≤8。
- Array.prototype.last总是undefined吗?国际单项体育联合会在铬36下不工作
- 对我来说,这是最好的答案。万岁是最好的
这里有更多的javascript艺术如果你来这里找它
根据使用reduceRight()的另一个答案的精神,但更短:
1
| [3, 2, 1, 5].reduceRight(a => a); |
它依赖于这样一个事实:如果您不提供初始值,则会选择最后一个元素作为初始元素(检查此处的文档)。由于回调只是不断返回初始值,最后一个元素将是最后一个返回的元素。
请注意,这应该被视为JavaScript艺术,决不是我推荐的方式,主要是因为它在O(n)时间内运行,但也因为它会损害可读性。
现在严肃的回答
我认为(考虑到你希望它比array[array.length - 1]更简洁)的最好方式是:
1
| const last = a => a[a.length - 1]; |
号
然后使用函数:
如果您处理上面使用的匿名数组(如[3, 2, 1, 5])时,该函数实际上很有用,否则您必须将其实例化两次,这将是低效和丑陋的:
1
| [3, 2, 1, 5][[3, 2, 1, 5].length - 1] |
。
呃。
例如,在这种情况下,您有一个匿名数组,需要定义一个变量,但是您可以使用last():
1
| last("1.2.3".split(".")); |
我认为最简单和超低效的方法是:
1 2 3
| var array = ['fenerbahce','arsenal','milan'];
var reversed_array = array.reverse(); //inverts array [milan,arsenal,fenerbahce]
console.log(reversed_array[0]) // result is"milan". |
。
- 这个解决方案需要更多的内存和时间。这真的不是理想的解决方案。
- 这是非常低效的。不要这样做。
- 不要这样做,这只是知识:)
- 为了得到最后一个元素而反转整个数组是非常低效的。
- 但这确实很容易。
- 可怕的想法!reverse更改了原始数组,因此如果连续运行两次,则会得到不同的结果(asuming length>1)
在ECMAScript Proposal Stage 1中,有一个建议添加一个数组属性,该属性将返回最后一个元素:Proposal Array Last。
语法:
1 2 3 4
| arr.lastItem // get last item
arr.lastItem = 'value' // set last item
arr.lastIndex // get last index |
号
您可以使用polyfill。
提案作者:Keith Cirkel(柴汽车)
我建议创建助手函数,并在每次使用它时都需要它。让函数更一般化,不仅可以得到最后一个项,还可以从最后一个项中获得第二个项等等。
1 2 3 4
| function last(arr, i) {
var i = i || 0;
return arr[arr.length - (1 + i)];
} |
用法很简单
1 2 3 4
| var arr = [1,2,3,4,5];
last(arr); //5
last(arr, 1); //4
last(arr, 9); //undefined |
号
现在,让我们解决原始问题
Grab second to last item form array. If the last item in the loc_array is"index.html" grab the third to last item instead.
号
下一行做这项工作
1
| last(loc_array, last(loc_array) === 'index.html' ? 2 : 1); |
所以,你需要重写
1
| var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2]))); |
。
以这种方式
1
| var newT = document.createTextNode(unescape(capWords(last(loc_array, last(loc_array) === 'index.html' ? 2 : 1)))); |
或者使用附加变量来提高可读性
1 2
| var nodeName = last(loc_array, last(loc_array) === 'index.html' ? 2 : 1);
var newT = document.createTextNode(unescape(capWords(nodeName))); |
。
- 看我的答案,很相似。我没有创建函数"last()"而是创建函数"w(thearray)",它返回一个具有方法"last()"的对象。
下面的情况如何?
1 2 3 4 5
| if ('index.html' === array[array.length - 1]) {
//do this
} else {
//do that
} |
。
如果使用下划线或lodash,则可以使用_.last(),例如:
1 2 3 4 5
| if ('index.html' === _.last(array)) {
//do this
} else {
//do that
} |
号
或者您可以创建自己的最后一个函数:
1
| const _last = arr => arr[arr.length - 1]; |
号
使用方法如下:
1 2 3 4 5
| if ('index.html' === _last(array)) {
//do this
} else {
//do that
} |
号
使用lodash_u.last(array)获取array的最后一个元素。
1 2 3
| data = [1,2,3]
last = _.last(data)
console.log(last) |
。
1
| <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"> |
号
使用ES6/ES2015 Spread Operator(…)可以执行以下操作。
1 2 3
| const data = [1, 2, 3, 4]
const [last] = [...data].reverse()
console.log(last) |
请注意,使用spread operator和reverse并没有改变原始数组,这是获取数组最后一个元素的纯方法。
- 为了得到最后一个元素而反转整个数组是非常低效的。
- @俚语,同意。如果你要做数亿到数百万次的手术,那么你必须考虑不要这样做,但是如果你只做几次,那么没有人会注意到这一点。此示例提供"pure"调用,而不更改实际的数据数组。
获取数组最后一项的简单方法:
1
| var last_item = loc_array.reverse()[0]; |
。
当然,我们需要先检查以确保数组至少有一个项。
- 这并不能回答这个问题。要评论或要求作者澄清,请在他们的帖子下面留下评论。-来自审阅
- 问题是"如何获取数组中的最后一项",我的解决方案应该是有效的。:)
- 这是获取最后一个元素的最慢方法…如果数组有一百万个元素呢?
- 可怕的想法!reverse更改了原始数组,因此如果连续运行两次,则会得到不同的结果(asuming length>1)
清洁高效:
1 2 3
| let list = [ 'a', 'b', 'c' ]
(xs => xs[xs.length - 1])(list) |
号
如果使用babel安装管道操作员,它将变为:
1
| list |> (xs => xs[xs.length - 1]) |
号
- 我非常喜欢那种生活句法。谢谢你让我的生活变得更加复杂。
另一个ES6唯一的选择是使用Array.find(item, index)=> {...})如下:
1 2
| const arr = [1, 2, 3];
const last = arr.find((item, index) => index === arr.length - 1); |
号
很少有实际价值,张贴显示索引也可用于您的过滤逻辑。
您也可以在不从URL提取数组的情况下实现此问题。
这是我的选择
1
| var hasIndex = (document.location.href.search('index.html') === -1) ? doSomething() : doSomethingElse(); |
!问候语?
这可以通过lodash _.last或_.nth来实现:
1 2 3
| var data = [1, 2, 3, 4]
var last = _.nth(data, -1)
console.log(last) |
1
| <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"> |
。
这个方法不会干扰你的原型。它还可以防御0长度的阵列,以及null/undefined阵列。如果返回的默认值可能与数组中的项匹配,则甚至可以重写默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const items = [1,2,3]
const noItems = []
/**
* Returns the last item in an array.
* If the array is null, undefined, or empty, the default value is returned.
*/
function arrayLast (arrayOrNull, defVal = undefined) {
if (!arrayOrNull || arrayOrNull.length === 0) {
return defVal
}
return arrayOrNull[arrayOrNull.length - 1]
}
console.log(arrayLast(items))
console.log(arrayLast(noItems))
console.log(arrayLast(null))
console.log(arrayLast(items, 'someDefault'))
console.log(arrayLast(noItems, 'someDefault'))
console.log(arrayLast(null, 'someDefault')) |
。
arrow函数通过不重复数组的名称,使执行速度最快的方法更加简洁。
1
| var lastItem = (a => a[a.length - 1])(loc_array); |
- 但是,当您可以直接访问最后一项时,为什么要编写一个方法…埃多克斯1〔6〕
- 不过,这并不能说明如何创建方法。它显示了在函数上下文中使用箭头函数将loc_数组"重命名"为a。这就像执行var getLast = a => a[a.length - 1]; var lastItem = getLast(loc_array),但是"getlast"函数是在一行中的,而不是单独定义的。
还有一个NPM模块,将last添加到Array.prototype中。
1
| npm install array-prototype-last --save |
使用
1 2 3 4 5
| require('array-prototype-last');
[1, 2, 3].last; //=> 3
[].last; //=> undefined |
。
- 功能来源?
- github.com/qalex/array-prototype-last/blob/master/index.js-在这里
- 是西玛拉吗?Array.prototype.last = function(){ return this[this.length - 1]; }+Object.defineProperty(Array.prototype, 'last', {enumerable: false});
- 在示例last is函数中,您应该像['a'、'b'].last()//'b'一样调用它,而在模块last is属性中,您可以像['a'、'b'].last/'b'一样调用它。
- 好吧,在代码中删除()是一件麻烦的事情,但这个"属性"实际上每次都是一个调用的函数,对吗?
- 是的,它是一个每次调用的函数
无论你做什么,都不要使用
reverse()!!!!
有几个答案提到了reverse,但没有提到reverse修改了原始数组,并且(在某些其他语言或框架中)没有返回副本。
1 2 3 4 5 6 7 8 9 10 11 12 13
| var animals = ['dog', 'cat'];
animals.reverse()[0]
"cat"
animals.reverse()[0]
"dog"
animals.reverse()[1]
"dog"
animals.reverse()[1]
"cat" |
号
这可能是要调试的最糟糕的代码类型!
- 不过,如果你刚从工作中被解雇,在你离开之前,这是一件有趣的小事情,可以加入代码库:—)
- 如果确实需要数组的反转副本,现在可以使用排列运算符。如[...animals].reverse()。
- 在使用反向[1,3,4,5,"last"].slice().reverse()[0]之前,您可以简单地复制数组。
要防止从源数组中删除最后一个项,可以使用
1
| Array.from(myArray).pop() |
号
主要支持所有浏览器(ES6)
使用还原光:
1
| [3,2,1,5].reduceRight((a,v) => a ? a : v); |
- 这实际上是一种非常有创意的方法,尽管它在O(N)时间内运行,因为它仍然遍历整个数组。
- 如果你不介意的话,我去掉了不必要的return和花括号,使它更加简洁。
带-1的array.prototype.slice可用于创建仅包含原始数组最后一项的新数组,然后可以使用析构函数赋值创建使用新数组第一项的变量。
1 2 3 4 5 6 7
| const lotteryNumbers = [12, 16, 4, 33, 41, 22];
const [lastNumber] = lotteryNumbers.slice(-1);
console.log(lotteryNumbers.slice(-1));
// => [22]
console.log(lastNumber);
// => 22 |
号
下面是一个干净的原型扩展,它可以简单地实现Aaron Harun的答案:
1 2 3 4
| Array.prototype.i = function(val){
if (val < 0) return this[this.length - Math.abs(val)]
return this[val]
} |
号
在定义了原型之后,这将起作用:
1 2 3 4
| arr = [1, 2, 3, 4, 5]
arr.i(0) // 1
arr.i(-1) // 5
arr.i(-2) // 4 |
号
这行吗?
1 2 3 4 5 6
| if (loc_array.pop() =="index.html"){
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-3])));
}
else{
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2])));
} |
号
- 不,因为.pop()返回最后一个元素并删除它,所以索引会更改。
- 如果不希望改变原始数组,那么执行arr.slice().pop()–这将创建一个新数组
使用ramda进行功能编程
如果您使用的是JS,我建议您查看Ramda,它是一个功能性编程库(除了更高级和模块化的库外,还包括lodash和underline)。Ramda提供了R.Last。
1 2 3 4 5 6
| import * as R from 'ramda';
R.last(['fi', 'fo', 'fum']); //=> 'fum'
R.last([]); //=> undefined
R.last('abc'); //=> 'c'
R.last(''); //=> '' |
还提供了init、head、tail。列出怪物(学习哈斯克尔)
。
- 包含库对于获取最后一个元素是不合理的,如果这样,我将使用下划线js.org/last
- @Tebe Ramda是一个更新的更现代的模块化版本的lodash,它是underline.js的替代品。
- 是的,我试过兰达,它尝起来有点不需要我第一眼就过分复杂了。也许我仍然认为功能不够,当我的思想准备好它的时候,我会进入它。顺便问一句,我知道你对它有经验,在兰达这样的代码看起来怎么样?_.chain([1,2,3]).map((val)=>返回val*2).first().value()->结果为2。它支持链接吗?我看到Ramda有方法链,但它看起来是为smth else设计的
- @像这样的R.pipe(R.take(1), x=>x*2)(也适用于typescript)
- 如果我们加上更多的链接,这个代码需要更多的邪恶嵌套吗?例如:"chain([1,2,3]).map((val)=>return val*2)。filter((val)=>return val>3;)。map((val)=>return val*2)。first().value()-paste.debian.net/1061022(请参阅带格式化代码的链接)-结果为8
- 不,pipe有不止一个函数const m = x => y => x * y; R.pipe(R.take(1), m(2), m(3), m(4))这里有什么意义?我是说我很乐意帮助你学习拉姆达,但这与我的答案无关?你似乎有点痛苦,因为你在努力摸索拉姆达,所以你对我投了反对票(这不是开始谈话的好方法)。但是继续学习。顺便说一句,你也可以做x = R.pipe( R.take(1), y=>y*2 ); y = R.pipe( x, z => z*2 )。
- 不管特雷弗怎么说,不幸的是,没有办法把这个拿回去。如果你的回答能让你感觉好一点的话,我会投赞成票。顺便说一句,我现在不想学,我只是想强调拉姆达错过了什么,而这让我一直处于强调状态。在temp变量中定义另一个函数是混乱的,而不是隐藏在链接中。
- 事实上,你不必这样做,我永远不会为你的案子那样做,我只会吹嘘不止一件事。这里的要点是,ramda正在用pipe进行函数组合。而Lodash所做的就是将对象包装在一个提供操作符作为方法的基类中。罗达什法是个很糟糕的主意。他们之所以这样做是因为使用lodash的遗留代码。例如,RXJS以前是这样做的,但现在它们也使用pipe方法。
- Pipe方法的一个巨大的实际优点是,任何库都可以导出与pipe一起使用的函数,并且只需要导入正在使用的函数。此外,任何您不使用的导入都会受到"树晃动"的影响,Webpack实际上可以在捆绑包中删除它(死代码会消失)。这使得ramba方法更纯粹(功能上)、更简洁(看我的例子)、更快(不包装对象)和更小(不需要导入类或所有运算符,并且可以删除不自动使用的运算符)
- @如果不能收回"你的意思是投反对票,你当然可以。如果用户编辑了答案,那么您可以收回投反对票。
- 再次感谢。所以看起来函数式编程有很多方面,Ramda只是在宣扬一种我以前不知道的方法。虽然不确定链条的坏处。它已经进入了ES6的核心。例如[1,2,3].filter((val)=>return val>1;).map((val)=>return val*2;).push()->生成2。我开始这一转变是因为我记得几年前我自己在想,当我想切换到Ramda的时候,却没有在FP中发现像链接imho这样的必要性。模块化和高级是很好的(如果真的是这样的话),不过我会以使用的便利性为赌注。
- @但是,尽管ES6采用了这种方法,但这种方法的缺点是相当明显的,例如,为了找到一个对象的键,你不做a.keys(),你做Object.keys(a)?为什么?因为可能有人把Object.prototype扩展到已经有keys,而es不想破坏向后兼容。但对于ramda方法来说这不是问题。R.pipe(R.keys, R.join(''))( {foo:1,bar:2} );你只是把函数组合在一起。
- 此外,使用Ramda和Lodash(希望不是ES6),人们创建库来扩展核心功能。扩展原型通常被认为是不好的。这就是为什么Lodash团队认为通过让所有对象(它们的操作符都使用包装器类的实例)重现这个问题是个好主意,这有点可笑。(任何一个拉达什的延伸都需要猴子来修补)。
- 我不明白为什么这个答案会被否决!拉姆达可以说比洛达什和下划线都好。它是纯粹的功能性和干净的,尽管如果有人不习惯功能性编程,可能有点难以理解。对于这个问题,这绝对是一个很好的答案,尽管我仍然不建议使用一个库,如果您只需要获取数组中的最后一个元素。