为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕村225694 2021-06-17 18:01:25
在 Javascript 中使用这种循环是否安全?denseArray = [1,2,3,4,5, '...', 99999]var x, i = 0while (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,undefined和NaN。这里是否存在“超出范围”的问题,或者我们可以将 Javascript 中的数组视为“无限”,因为长内存未满?undefined 是否意味着浏览器可以将其设置为任何值,因为它是未定义的,还是我们可以认为条件测试始终有效?Javascript 中的数组很奇怪,因为“它们是对象”,所以最好问一下。我无法找到使用这些标签#2的答案: [javascript] [sentinel] [while-loop] [arrays]。它给出零结果!我已经考虑了一段时间并使用它足以开始担心。但我想使用它,因为它优雅、易于查看、简短,可能在大数据中有效。i数组的大小很有用。更新@Barmar 告诉:JS 保证未初始化的数组元素将返回未定义的值。MDN 确认:使用无效的索引号返回未定义。@schu34 的注释:最好使用denseArray.forEach((x)=>{...code})针对其用途进行优化并为开发人员所知的。无需遇到虚假值。它有很好的浏览器支持。
查看完整描述

2 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

即使您的代码以后不会被其他人查看,最好使其尽可能具有可读性和组织性。条件测试中的赋值(增量和减量运算符除外)通常是一个坏主意。


您的支票也需要更具体一点,因为[0, '']两者都评估为假。


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


for(let i = 0; i < denseArray.length; i++) {

  let x = denseArray[i]

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

  console.log(x);

  if (/* check bad value */) break;

}


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

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

根据我的经验,如果以可读性甚至可靠性为代价,那么节省几行通常是不值得的。


编辑:这是我用来测试速度的代码


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++) {

  x = arr[i];

  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++) {

  x = arr[i];

  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++) {

  x = arr[i];

  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 语句来检查错误的值,而且速度仍然更快。


查看完整回答
反对 回复 2021-06-24
?
慕的地10843

TA贡献1785条经验 获得超8个赞

搜索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() )

{

  ...do something with var 

}

否则必须写出来


var = GetNext();

while( var )

{

 ...do something

 var = GetNext();

}

一般来说,最好使用denseArray.forEach((x) => { ... })开发人员众所周知的。无需考虑虚假值。它有很好的浏览器支持。但是速度很慢!


我做了一个 jsperf,显示forEach 比 while 慢 60%!测试还显示,在我的机器上for比while,稍快!另请参阅@Albert 的回答,测试表明for 比 while 稍快。


虽然这种使用while是安全的,但它可能不是无错误的。在编码时,您可能知道自己的数据,但您不知道是否有人复制粘贴代码以用于其他数据。


查看完整回答
反对 回复 2021-06-24
  • 2 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信