JavaScript — прототипированное имя функции, возвращаемое как ключ ассоциативного массива

#javascript #arrays #prototype-programming

#JavaScript #Массивы #прототип-программирование

Вопрос:

Я хочу добавить прототипную функцию к объекту массива javascript.

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

Вот пример, иллюстрирующий проблему:

 <html>
  <head>
    <script type="text/javascript">
      Array.prototype.foo = function () {
        // do something
      }
      function keys() {
        var fruit = ["apples","pears","bannanas"];
        for (key in fruit) alert(key); // alerts: 0, 1, 2, foo
      }
    </script>
  </head>
  <body onload="keys();">
  </body>
</html>
 

Есть идеи о том, как я могу обойти это?

Мне не нужно создавать прототип функции, но, с точки зрения удобства чтения, я бы предпочел.

РЕДАКТИРОВАТЬ: просто для ясности, реализация в реальном мире приведенного выше примера повторяется через ассоциативный массив, следовательно for..in петля

РЕДАКТИРОВАТЬ: Спасибо за ответы, ребята, но я думаю, что вы упускаете то, что мне нужно. Что я хочу знать, так это могу ли я добавить прототипную функцию к объекту массива javascript (или объявить функцию другим способом, который имел бы тот же эффект), без изменения имени функции при итерации по массиву через for..in петля. Возьмем indexOf , к примеру, функцию. Javascript, похоже, определяет его внутренне таким образом, что он не отображается в ключах объекта / массива (верно?). Можно ли воспроизвести такое же поведение во время выполнения?

Комментарии:

1. Не используйте a for...in для итерации по массиву. Используйте обычный for цикл, и тогда у вас не будет этой проблемы.

2. Да, если это не ассоциативный массив — я не знаю способа перебора ассоциативного массива без использования for..in петля..

3. или вы можете сделать это, но проверить, что тип не является функцией, если (fruit[key].constructor != функция)

4. Вы должны обновить свой пример, чтобы показать это.

5. В JavaScript нет «ассоциативных массивов». Есть объекты и массивы. Массивы — это просто объекты со специальным свойством длины и некоторыми удобными методами. Объекты — это просто неупорядоченные пакеты пар имя / значение.

Ответ №1:

Вам нужно проверить, находится ли fruit.hasOwnProperty(key) в цикле.

Комментарии:

1. Спасибо, это пригодится

Ответ №2:

Чтобы избежать унаследованных перечислимых свойств с for..in , используйте тест hasOwnProperty:

 for (var p in obj) {
  if (obj.hasOwnProperty(p)) {
    // p is a property of obj and not inherited
  }
}
 

Использование for..in использование массивов не рекомендуется — если вам нужен объект, используйте объект.

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

Ответ №3:

Как говорит Джеймс, используйте, а не…

 function keys() {
  var fruit = ["apples", "pairs", "bananas"];
  for(var key in fruit) {
    alert(key);
  }
}
 

Вместо этого выполните следующее…

 function keys() {
  var fruit = ["apples", "pairs", "bananas"];
  for(var i = 0; i < fruit.length;   i) {
    alert(i);
  }
}
 

Поскольку свойство length будет обновляться только с элементами индексированного массива, а не с элементами, добавленными в прототип.

Ответ №4:

Чтобы выполнить итерацию через ассоциативный массив с помощью for in и получить то, что вы хотите, я бы использовал typeof для проверки правильности ввода и ограничения на не-функции. Вы можете использовать number , string , boolean , object , function и undefined с typeof http://msdn.microsoft.com/en-us/library/259s7zc1(v=vs.94).aspx

Ответ №5:

Я ценю, что это не всегда доступно, но вы можете избежать всей этой путаницы, используя Array#forEach или, если вы используете библиотеку JavaScript (вполне вероятно и настоятельно рекомендуется), тогда у вас есть что-то вроде Prototype Enumerable#each() , Sugar Array#each() или jQuery $.each() .