#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()
.