在 Javascript while 循环中使用 'undefined' 作为标记是否安全?
Is it safe to use 'undefined' as sentinel in a Javascript while loop?
在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 循环更短,而且对于大数组可能更有效。 sentinel 标记调用者发生了一些非常不寻常的事情.
数组必须是 才能工作!这意味着 没有其他 undefined
值,除了数组中最后一个元素之后的值。我几乎从不使用稀疏数组,只使用密集数组,所以这对我来说没问题。
要记住的另一个更重要的一点(感谢@Jack Bashford 提醒)是这不仅仅是未定义为哨兵。如果数组值为 0、false 或任何其他假值,循环将停止 。所以,你必须确定数组中的数据没有 falsy values 即 0
, ""
, ''
, ``, null
, undefined
和 NaN
。
这里有什么 "out of range" 的问题吗,或者我们可以将 Javascript 中的数组视为 "infinite",因为 long 内存未满?
undefined 是否意味着浏览器可以将其设置为任何值,因为它是未定义的,或者我们是否可以认为条件测试始终有效?
Javascript 中的数组很奇怪,因为 "they are Objects" 最好问一下。
我无法使用这些标签在 Whosebug 上找到答案:[javascript] [sentinel] [while-loop] [arrays]
。 结果为零!
这个问题想了很久,用得够多了,开始担心了。但我想使用它,因为它优雅、易于查看、简短,也许在大数据中有效。 i
是数组的大小很有用。
更新
- @Barmar 告诉:JS保证未初始化的数组
元素将 return 值未定义。
- MDN confirms: 正在使用
无效的索引号 returns undefined.
- @schu34 的注释:最好使用针对其用途优化并为开发人员所知的
denseArray.forEach((x)=>{...code})
。无需遇到虚假值。它有 good browser support。
即使您的代码以后不会被其他人查看,最好让它尽可能具有可读性和组织性。条件测试中的赋值(递增和递减运算符除外)通常不是一个好主意。
您的检查也需要更具体一些,因为 [0, '']
两者的计算结果均为 false。
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 语句来检查错误值,而且速度仍然更快。
搜索 javascript assignment in while
得到结果:
观点与 it looks like a common error where you try to compare values to If there is quirkiness in all of this, it's the for statement's wholesale divergence from the language's normal syntax 不同。 for
是添加冗余的语法糖。它并没有与 if-goto
一起过时 while
。
首要问题是它是否安全。 MDN 说:Using an invalid index number returns undefined 在 Array 中,因此可以安全使用。条件下的作业测试是安全的。多个赋值可以同时完成,但是带有 var
、let
或 const
的声明不像 assign 那样 return,所以声明必须在条件之外.发表评论,以便将来向其他人或您自己解释数组必须保持密集且没有虚假值,否则 它可能会出错 。
允许 false
、0
或 ""
(除 undefined
之外的任何虚假)然后将其扩展为:while ((x = denseArray[i++]) !== undefined) ...
但这样并没有更好比普通的数组长度比较。
有用吗? Yes:
while( var = GetNext() )
{
...do something with var
}
否则必须写
var = GetNext();
while( var )
{
...do something
var = GetNext();
}
一般来说最好使用开发者熟知的denseArray.forEach((x) => { ... })
。无需考虑虚假值。它有 good browser support。 但是它很慢!
I made a jsperf 显示 forEach 比 while 慢 60%!测试还显示 for
在我的机器上比 while
稍快!另请参阅@Albert 的回答,测试表明 for 比 while.
稍快
虽然 while
的这种使用是安全的 它可能不是没有错误。在编码时,您可能知道您的数据,但您不知道是否有人 copy-paste 将代码用于其他数据。
在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 循环更短,而且对于大数组可能更有效。 sentinel 标记调用者发生了一些非常不寻常的事情.
数组必须是 undefined
值,除了数组中最后一个元素之后的值。我几乎从不使用稀疏数组,只使用密集数组,所以这对我来说没问题。
要记住的另一个更重要的一点(感谢@Jack Bashford 提醒)是这不仅仅是未定义为哨兵。如果数组值为 0、false 或任何其他假值,循环将停止 。所以,你必须确定数组中的数据没有 falsy values 即 0
, ""
, ''
, ``, null
, undefined
和 NaN
。
这里有什么 "out of range" 的问题吗,或者我们可以将 Javascript 中的数组视为 "infinite",因为 long 内存未满? undefined 是否意味着浏览器可以将其设置为任何值,因为它是未定义的,或者我们是否可以认为条件测试始终有效? Javascript 中的数组很奇怪,因为 "they are Objects" 最好问一下。
我无法使用这些标签在 Whosebug 上找到答案:[javascript] [sentinel] [while-loop] [arrays]
。 结果为零!
这个问题想了很久,用得够多了,开始担心了。但我想使用它,因为它优雅、易于查看、简短,也许在大数据中有效。 i
是数组的大小很有用。
更新
- @Barmar 告诉:JS保证未初始化的数组 元素将 return 值未定义。
- MDN confirms: 正在使用 无效的索引号 returns undefined.
- @schu34 的注释:最好使用针对其用途优化并为开发人员所知的
denseArray.forEach((x)=>{...code})
。无需遇到虚假值。它有 good browser support。
即使您的代码以后不会被其他人查看,最好让它尽可能具有可读性和组织性。条件测试中的赋值(递增和递减运算符除外)通常不是一个好主意。
您的检查也需要更具体一些,因为 [0, '']
两者的计算结果均为 false。
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 语句来检查错误值,而且速度仍然更快。
搜索 javascript assignment in while
得到结果:
观点与 it looks like a common error where you try to compare values to If there is quirkiness in all of this, it's the for statement's wholesale divergence from the language's normal syntax 不同。 for
是添加冗余的语法糖。它并没有与 if-goto
一起过时 while
。
首要问题是它是否安全。 MDN 说:Using an invalid index number returns undefined 在 Array 中,因此可以安全使用。条件下的作业测试是安全的。多个赋值可以同时完成,但是带有 var
、let
或 const
的声明不像 assign 那样 return,所以声明必须在条件之外.发表评论,以便将来向其他人或您自己解释数组必须保持密集且没有虚假值,否则 它可能会出错 。
允许 false
、0
或 ""
(除 undefined
之外的任何虚假)然后将其扩展为:while ((x = denseArray[i++]) !== undefined) ...
但这样并没有更好比普通的数组长度比较。
有用吗? Yes:
while( var = GetNext() )
{
...do something with var
}
否则必须写
var = GetNext();
while( var )
{
...do something
var = GetNext();
}
一般来说最好使用开发者熟知的denseArray.forEach((x) => { ... })
。无需考虑虚假值。它有 good browser support。 但是它很慢!
I made a jsperf 显示 forEach 比 while 慢 60%!测试还显示 for
在我的机器上比 while
稍快!另请参阅@Albert 的回答,测试表明 for 比 while.
虽然 while
的这种使用是安全的 它可能不是没有错误。在编码时,您可能知道您的数据,但您不知道是否有人 copy-paste 将代码用于其他数据。