猿问

在 Javascript while 循环中使用“未定义”作为哨兵是否安全?

在 Javascript 中使用这种循环是否安全?


denseArray = [1,2,3,4,5, '...', 99999]


var x, i = 0

while (x = denseArray[i++]) {

    document.write(x + '<br>')  

    console.log(x)  

}


document.write('Used sentinel: ' + denseArray[i])

document.write('Size of array: ' + i)  

它比 for 循环更短,并且对于大数组可能更有效,使用内置哨兵。一个定点 标志主叫方的事实,一些很出的最普通的发生

阵列必须是密集阵列才能工作!这意味着除了数组中最后一个元素之后的值之外,没有其他 undefined 。我几乎从不使用稀疏数组,只使用密集数组,所以这对我来说没问题。

要记住的另一个更重要的点(感谢@Jack Bashford 提醒)是这不仅仅是未定义为哨兵。如果数组值为 0、false 或任何其他虚假值,则循环将停止。因此,您必须确保数组中的数据没有虚假值,即0""'', ``, null,undefinedNaN

这里是否存在“超出范围”的问题,或者我们可以将 Javascript 中的数组视为“无限”,因为长内存未满?undefined 是否意味着浏览器可以将其设置为任何值,因为它是未定义的,还是我们可以认为条件测试始终有效?Javascript 中的数组很奇怪,因为“它们是对象”,所以最好问一下。

我无法找到使用这些标签#2的答案: [javascript] [sentinel] [while-loop] [arrays]它给出零结果

我已经考虑了一段时间并使用它足以开始担心。但我想使用它,因为它优雅、易于查看、简短,可能在大数据中有效。i数组的大小很有用。

更新

  • @Barmar 告诉:JS 保证未初始化的数组元素将返回未定义的值。

  • MDN 确认使用无效的索引号返回未定义。

  • @schu34 的注释:最好使用denseArray.forEach((x)=>{...code})针对其用途进行优化并为开发人员所知的。无需遇到虚假值。它有很好的浏览器支持


慕村225694
浏览 135回答 2
2回答

慕码人8056858

即使您的代码以后不会被其他人查看,最好使其尽可能具有可读性和组织性。条件测试中的赋值(增量和减量运算符除外)通常是一个坏主意。您的支票也需要更具体一点,因为[0, '']两者都评估为假。denseArray = [1,2,3,4,5, '...', 99999]for(let i = 0; i < denseArray.length; i++) {&nbsp; let x = denseArray[i]&nbsp; document.write(x + '<br>');&nbsp; console.log(x);&nbsp; if (/* check bad value */) break;}document.write('Used sentinel: ' + denseArray[i])document.write('Size of array: ' + i)&nbsp;&nbsp;根据我的经验,如果以可读性甚至可靠性为代价,那么节省几行通常是不值得的。编辑:这是我用来测试速度的代码const arr = [];let i;for (i = 0; i < 30000000; i++) arr.push(i.toString());let x;let start = new Date();for(i = 0; i < arr.length; i++) {&nbsp; x = arr[i];&nbsp; if (typeof x !== 'string') break;}console.log('A');console.log(new Date().getTime() - start.getTime());start = new Date();i = 0;while (x = arr[i++]) {}console.log('B');console.log(new Date().getTime() -start.getTime());start = new Date();for(i = 0; i < arr.length; i++) {&nbsp; x = arr[i];&nbsp; if (typeof x !== 'string') break;}console.log('A');console.log(new Date().getTime() - start.getTime());start = new Date();i = 0;while (x = arr[i++]) {}console.log('B');console.log(new Date().getTime() -start.getTime());start = new Date();for(i = 0; i < arr.length; i++) {&nbsp; x = arr[i];&nbsp; if (typeof x !== 'string') break;}console.log('A');console.log(new Date().getTime() - start.getTime());start = new Date();i = 0;while (x = arr[i++]) {}console.log('B');console.log(new Date().getTime() -start.getTime());for 循环甚至有一个额外的 if 语句来检查错误的值,而且速度仍然更快。

慕的地10843

搜索javascript assignment in while给定的结果:意见有所不同,它看起来像一个常见的错误,您尝试将值与以下内容进行比较如果所有这些都存在古怪之处,则是 for 语句与语言的正常语法完全不同。这for是添加冗余的语法糖。它没有过时while一起if-goto。首先的问题是它是否安全。MDN 说:使用无效的索引号会在 Array 中返回 undefined,因此使用它是安全的。在条件下对作业进行测试是安全的。多个赋值可以在同一个中完成,但是带有var, letor的声明const不会像assign do那样返回,因此声明必须在条件之外。有一个评论,以便将来向其他人或您自己解释数组必须保持密集而没有虚假值,否则它可能会出错。允许false,0或""(除了 任何虚假undefined)然后将其扩展为:while ((x = denseArray[i++]) !== undefined) ...但它并不比普通的数组长度比较好。有用吗?是:while( var = GetNext() ){&nbsp; ...do something with var&nbsp;}否则必须写出来var = GetNext();while( var ){&nbsp;...do something&nbsp;var = GetNext();}一般来说,最好使用denseArray.forEach((x) => { ... })开发人员众所周知的。无需考虑虚假值。它有很好的浏览器支持。但是速度很慢!我做了一个 jsperf,显示forEach 比 while 慢 60%!测试还显示,在我的机器上for比while,稍快!另请参阅@Albert 的回答,测试表明for 比 while 稍快。虽然这种使用while是安全的,但它可能不是无错误的。在编码时,您可能知道自己的数据,但您不知道是否有人复制粘贴代码以用于其他数据。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答