Безопасно ли использовать «undefined» в качестве часового в цикле Javascript while? - PullRequest
1 голос
/ 09 июня 2019

Безопасно ли использовать этот тип цикла в 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, и, возможно, также более эффективно для больших массивов использовать встроенный сторож.A sentinel указывает вызывающей стороне на тот факт, что произошло нечто необычное .

Массив должен быть плотным массивом на работу!Это означает, что нет другого значения undefined , кроме значения, которое идет после последнего элемента в массиве .Я почти никогда не использую разреженные массивы, только плотные массивы, так что это нормально для меня.

Еще один важный момент, о котором следует помнить (спасибо @Jack Bashford), это , который не просто не определен в качестве дозорного.Если значение массива 0, false или любое другое ложное значение, цикл остановится .Таким образом, вы должны быть уверены, что данные в массиве не имеют ложных значений , то есть 0, "", '', ``, null, undefined и NaN.

Есть ли здесь какая-то проблема «вне диапазона», или мы можем считать массивы в Javascript «бесконечными», поскольку длинная память не заполнена?Означает ли неопределенное, что браузеры могут установить для него любое значение, потому что оно не определено, или мы можем считать, что условный тест всегда работает?Массивы в Javascript странны, потому что «они являются объектами», поэтому лучше спросить.

Я не могу найти ответ по Stackoverflow, используя следующие теги: [javascript] [sentinel] [while-loop] [arrays]. Это дает нулевой результат !

Я думал об этом некоторое время и использовал его достаточно, чтобы начать беспокоиться.Но я хочу использовать это, потому что это элегантно, легко увидеть, коротко, возможно, эффективно для больших данных.Полезно, чтобы i был размером массива.

ОБНОВЛЕНИЯ

  • @ Бармар сказал: JS гарантирует, что неинициализированный массивэлемент вернет значение undefined.
  • MDN подтверждает : Использование неверного номера индекса возвращает неопределенное значение.
  • Примечание @ schu34: Лучше использовать denseArray.forEach((x)=>{...code}), оптимизированный для его использования и известный разработчикам.Не нужно сталкиваться с ложными ценностями.Он имеет хорошую поддержку браузера .

Ответы [ 2 ]

1 голос
/ 09 июня 2019

Даже если впоследствии ваш код не будет просматриваться другими пользователями, рекомендуется сделать его максимально читабельным и упорядоченным.Присвоение значений в тестировании условий (за исключением операторов увеличения и уменьшения), как правило, является плохой идеей.

Ваша проверка также должна быть более конкретной, так как [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 для проверки на неправильные значения и все еще быстрее.

0 голосов
/ 09 июня 2019

Поиск javascript assignment in while дал результаты:

Мнения варьируются от похоже, что это общая ошибка, когда вы пытаетесь сравнить значения с . Если во всем этом есть причудливость, то это полное отклонение оператора от нормального синтаксиса языка . for - это синтаксическая избыточность добавления сахара. Он не устарел while вместе с if-goto.

Вопрос в первую очередь в том, безопасно ли это. MDN говорит: Использование недопустимого номера индекса возвращает неопределенное значение в массиве, поэтому его можно безопасно использовать. Проверка заданий в состоянии безопасна. В одном и том же может быть выполнено несколько присваиваний, но объявление с var, let или const не возвращает как присвоение, поэтому объявление должно быть вне условия. Получите комментарий, чтобы объяснить другим или себе в будущем, что массив должен оставаться плотным без ложных значений, потому что в противном случае может привести к ошибке .

Чтобы разрешить 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 , который показал , так как каждый на 60% медленнее, чем ! Тест также показывает, что for немного быстрее, чем while, на моей машине! См. Также ответ @Albert с тестовым показом, что для немного быстрее, чем в то время как .

Хотя использование while безопасно , оно не может быть безошибочным . Во время кодирования вы можете знать свои данные, но вы не знаете, копирует ли кто-нибудь код для использования в других данных.

...