Правильное использование цикла "for...in" в javascript?

Теперь я хотел бы получить некоторые указания о том, как правильно использовать цикл "for...in" в JavaScript, я уже провел некоторые исследования и попробовал пару вещей, но мне все еще не ясно, как правильно его использовать.

Давайте я у вас есть случайное число тегов "select" в HTML-форме, и я не требую, чтобы пользователь выбирал опцию для всех из них, они могут оставить некоторые нетронутыми, если захотят. Однако мне нужно знать, выбрали ли они ни одного или хотя бы одного.

способ, которым я пытаюсь выяснить, выбрал ли пользователь какой-либо из них, используя цикл "for...in". Например:

var allSelected = $("select option:selected");
var totalSelected = $("select option:selected").length;

первая переменная создает массив всех выбранных параметров. Вторая переменная говорит мне, сколько выбрано параметры, которые у меня есть в форме (выбор тегов может быть более одного, и он меняется каждый раз). Теперь, чтобы увидеть, выбран ли какой-либо из них, я перебираю каждый элемент (выбранная опция) и извлекаю атрибут "value". Тег "option" по умолчанию имеет значение= "0", поэтому, если какой-либо выбранный параметр возвращает значение больше 0, я знаю, что по крайней мере один параметр был выбран, однако он не должен быть в порядке, это мой цикл до сих пор:

for(var i = 0; i < totalSelected; i++){
  var eachOption = $(allSelected[i]).val();
  var defaultValue = 0;
  if(eachOption == defaultValue){
    ...redirect to another page
  }else if(eachOption > defaultValue){
    ... I display an alert
  }
}

моя проблема здесь в том, что как только "если" соответствует значению 0, он отправляет пользователя на следующую страницу без тестирования остальных элементов массива, и пользователь может выбрать второй или третий вариант.

то, что я действительно хочу сделать, это проверить все элементы в массиве, а затем предпринять следующее действие, на мой взгляд, это то, как я мог бы это сделать, но я не получаю это правильно:

var randomValue = 25;  
for(randomValue in allSelected){
  var found = true;
  var notFound = false
  if(found){
    display an alert
  }else{
    redirect to next page
  }
}

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

Я надеюсь, что это имеет смысл для вас, ребята, любая помощь будет оценена.
Спасибо,
JC

5 ответов


более простой способ написать (что я думаю), что вы пытаетесь достичь с помощью .each()

// this is to know if we want to redirect
var redir = true;
$("select option:selected").each(function() {
  var val = $(this).val();

  if (val > 0) {
    alert('Found one!');
  }      
  if (val != 0) { 
    redir = false;
    // you can return false here if you want to stop processing the each loop too!
  } 
});

if (redir) {
  window.location = "/nextpage";
}

for..in (вообще)

for..in перебирает имена свойств объекта. Люди думают, что он проходит через индексы массива, потому что индексы массива are имена свойств объекта array, но это неправильное представление.

так:

var obj = {foo: 1, bar: 2};

foo и bar являются именами свойств, и так:

var name;
for (name in obj) {
    alert(name);
}

...покажет "foo" и " bar "(в частности порядок.)

мы вернемся к массивам через минуту. :-) Давайте сначала посмотрим на объекты.

объекты могут иметь собственные свойства и свойства, которые они наследуют от объектов-прототипов. The foo и bar свойства выше были прямыми свойствами obj, но:

function Thing() {
}
Thing.prototype.foo = 1;

var t = new Thing();
t.bar = 2;

теперь наш!--11-- объект> имеет foo и bar, а foo происходит от прототип, а bar является его собственностью. В for..in, мы может проверить, что есть что:

var name;
for (name in obj) {
    alert(name + "(" + (obj.hasOwnProperty(name) ? "own" : "inherited") + ")");
}

...который покажет "foo (унаследованный)" и "bar (собственный)" (в определенном порядке).

объекты могут иметь свойства, которые являются неперечислимый - они не появляются в for..in петли. Вот почему, если вы делаете for..in на массив,length свойство не отображается, потому что length определяется как не перечисляемое свойство. Почти все стандартные свойства стандартных объектов не подлежат перечислению (в том числе все из тех, которые указывают на функции, такие как toUpperCase собственности на String экземпляров). (Раньше было, что только те, которые в спецификации могут быть не перечисляемыми, но ECMAScript 5th edition теперь предоставляет нам способы иметь наши собственные не перечисляемые свойства.)

Итак, массивы. Массивы в JavaScript не похожи на массивы в большинстве других языков. (Во-первых, это не непрерывные блоки памяти.) Массив в JavaScript является стандартным объектом с несколько специальных поведений:

  • на length свойство всегда устанавливается на следующее число над именем свойства с наибольшим числовым значением, которое имеет объект массива. Поэтому, если ваш самый высокий индекс массива 2, потом length будет 3.
  • если вы измените length, любое свойство, имя которого имеет числовое значение, равное или выше числа, которое вы даете length будет удален из объекта.

это и функции они наследуют от Array.prototype в значительной степени все, что особенное в массивах в Javascript. Все их основные функции (хранение и извлечение значений) - это только стандартное поведение свойств объекта Javascript.

ваш конкретный цикл

по вышеуказанным причинам я бы не использовал for..in для вашего цикла. Я бы использовал jQuery#each или скучная старомодная петля, как у вас. Последнее выглядело бы так:

var allSelected = $("select option:selected");
var totalSelected = allSelected.length; // <= No need to repeat the selector query
var index;
var anySelected = false;
for (index = 0; !anySelected && index < totalSelected; ++index) {
    if (allSelected[index].value !== "0") {
        anySelected = true;
    }
}
if (anySelected) {
    // do something with the selection
}
else [
    // do something about their not having picked one
}

вы должны знать, что for-in оператор в JavaScript предназначен для перечислить свойства объекта.

если вы хотите итерации над массивом-как1 объект, последовательный цикл (for, while, do...while) всегда рекомендуется.

почему вы не должны использовать for-in для массивов объектов:

  • порядок итерации не гарантированные
  • наследуемые свойства также перечисляются

Читайте также:

[ 1] By массив-как я имею в виду любой объект, содержащий последовательно пронумерованные свойства и length собственность.


есть два аспекта вашего вопроса.

  1. использовать "для ... в" только для перебора имен свойств объектов и никогда перебирать массивы (либо реальные массивы, либо вещи, которые более или менее похожи на массивы, такие как объекты jQuery).

  2. Если вы используете jQuery, то это контр-идиоматические, чтобы делать это таким образом:

    $("select option:selected).each(function() {
      // .. "this" points to each option
    });

Если вы хотите собрать все настройки все выбирает, вы можете перебирать все на <select> теги, отфильтровать те, которые установлены только на их значение" по умолчанию", а затем собрать все значения в массиве пар имя/значение.


Я бы сделал что-то вроде этого

<html>
<head>
  <title>Test Page</title>
  <script src="http://code.jquery.com/jquery-latest.js"></script>
  <script type="text/javascript">

  $(function()
  {
    function checkSelected()
    {
      var DEFAULT = "0";
      var selected = [];

      $("select option:selected").each( function()
      {
        var $option = $(this);
        var optionValue = $option.val(); 
        if ( optionValue !== DEFAULT )
        {
          selected.push( {name: $option.parent().attr( 'name' ), value: optionValue } );
        }
      });

      if ( selected.length )
      {
        $.each( selected, function( index, item )
        {
          alert( item.name + ': ' + item.value );        
        });
      } else {
        alert( 'None selected!' );
      }
    }

    // just for this demo
    $('button').click( function( event )
    {
      event.preventDefault();
      checkSelected();
    })
  });


  </script>
</head>

<body>

<select name="one">
  <option value="0">Zero</option>
  <option value="1">One</option>
</select>

<select name="two">
  <option value="0">Zero</option>
  <option value="1">One</option>
</select>

<button>Test It</button>

</body>
</html>