javascript проверка существования элемента

Вопрос к знатокам! В JS не силен по этому прошу помощи!

Есть js скрипт, выводит определенное значение value в поле input id, по умолчанию скрипт отрабатывает на всем сайте, но сама форма находится не на всех страницах сайта, и на страницах где нет данного поля, выходит ошибка: Cannot read property ‘setAttribute’ of null, там где есть поле, данная ошибка не замечалась.

Так вот вопрос, как изменить скрипт, что бы, проходила проверка «существования» поля inpet id на странице сайта? Если есть, то выводим, нет, то не выводим!? Получается на странице не может найти поле и выводит ошибку!

Как в JavaScript правильно проверить наличие элемента в массиве по ключу?
Я как понимаю arr['one'] будет равняться undefined если такого элемента нету. Но у меня может сам элемент быть, просто значение у него undefined по некоторым причинам реализации кода. Как проверить на 100% именно присутствие элемента в массиве!

Да, поэтому нужно сделать следующим образом:

Есть конструкция in и она используется не только в цикле for-in

Ну например можно использовать так:

Внимание: Он проверяет не значение, а именно ключ, если нужно проверить есть ли значение 6 например, то нужно использовать следующую функцию.

Добавить комментарий Отменить ответ

Для отправки комментария вам необходимо авторизоваться.

Есть массив: [‘dog’, ‘cat’, ‘hamster’, ‘bird’, ‘fish’] , нужно вывести в консоль true , если массив содержит dog и false — если такой элемент отсутствует, но насколько я понимаю доступ к элементу в массиве проходит по номеру array[..] , каким образом можно проверить наличие того или иного элемента?

4 ответа 4

Используйте метод indexOf

Задача поиска элемента в массиве стоит перед всеми достаточно часто и хорошо бы расписать, как это можно сделать.

Ищут обычно в массиве элементы типа Number , String или Object . Естественно, самый быстрый способ поиска — по элементам типа Number , сравнение числа, даже очень большого, происходит очень быстро, гораздо проще проверить один элемент, чем лексиграфически сравнивать строки, а с объектами вообще другая история. Если мы ищем именно тот объект, который мы добавили в массив, то есть сравниваем ссылки — это так же быстро, как и сравнивать числа, а вот если же надо искать по свойствам объекта, то это может весьма и весьма затянуться. В особо сложных случаях, советую составлять какой-нибудь хэш объекта и строить отдельным массив-карту, в которой уже спокойно искать всё, что надо найти.

Разберем 6 способов сделать это на нативном JS разной новизны и 3 способа с их разбором на популярных фреймворках: jQuery, underscore и lodash.

Часть первая, нативная, в стиле аллегро

Для начала надо пройтись по родным возможностям языка и посмотреть, что можно сделать самим.

Поиск в лоб

Попробуем просто идти по элементам массива, пока мы не встретим то, что нам нужно. Как всегда самое простое решение является в среднем самым быстрым.

Работает везде. Сравнивает строго, с помощью === . Легко можно заменить на == , бывает полезно, когда элементы массива разных типов, но может замедлить поиск. Его можно и модифицировать, добавив возможность начинать поиск элемента с конца. Шикарно ищет цифры, строки. Немного расширив, можно добавить возможность поиска элемента по своему условию (это поможет нам искать по свойствам объекта или, например, первый элемент, который больше 100500):

Array.prototype.indexOf()

Array.prototype.indexOf(searchElement[, fromIndex = 0]) — старый добрый метод, заставляющий всех мучиться со своей -1 в случае, когда элемента нет.

Поддерживается он везде, кроме IE === . Увы, по свойствам объекта мы так искать не сможем. arr.indexOf(searchElement, fromIndex) принимает два аргумента, первый searchElement — это элемент который ищем, а второй, fromIndex , индекс с которого начнем искать (отрицательный говорит интерпретатору начинать поиск с arr.length + fromIndex индекса). Аккуратней, если вы укажете fromIndex больше длины массива, метод нераздумывая вернёт -1 .

Array.prototype.lastIndexOf()

Array.prototype.lastIndexOf(searchElement[, fromIndex = arr.length — 1]) — справедливости ради надо рассказать и про него. Работает полностью аналогично Array.prototype.indexOf() , но только полностью наоборот (поиск идет в обратном порядке и fromIndex изначально отсчитывается с конца). Заменил конструкцию ret != -1 на !!

ret ради забавы.

Array.prototype.find()

Array.prototype.find(callback[, thisArg]) — модный стильный и молодежный ES6, со всеми вытекающими:

Возвращает элемент или -1 , если ничего не найдено. Ищет с помощью callback(elem, index, arr) , то есть, если эта функция вернет true , то это именно тот самый, искомый элемент. Конечно, эту функцию можно задавать самому, поэтому метод универсален.

Array.prototype.findIndex()

Array.prototype.findIndex(callback[, thisArg]) — полностью аналогичный предыдущему метод, за исключением того, что функция возвращает не элемент, а индекс. Забавы ради сделаю её с возможностью передать свою функцию:

Array.prototype.includes()

Array.prototype.includes(searchElement[, fromIndex]) — а это уже ES7, с ещё пока оочень сырой поддержкой. Наконец-то у нас будет специальный метод, чтобы узнать, есть ли элемент в массиве! Поздравляю!

Это всё, что нужно, чтобы найти элемент. Аргументы у этой функции полностью аналогичны Array.prototype.indexOf() . А вот вернет он true в случае успеха и false в обратном. Естественно искать по свойствам объектов нельзя, для этого есть Array.prototype.find() . Должен быть самым быстрым, но. Возможно, что он и станет со временем самым быстрым.

Часть вторая, со вниманием, но чужая и в стиле сонаты

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

jQuery

jQuery.inArray(value, array [, fromIndex ]) — между прочим весьма быстрый метод, по тестам.

Использует внутри строгое равенство === и возвращает -1 , если ничего не нашел, а если все таки нашёл, то вернет его индекс. Для удобства и одинаковости обернем её в функцию:

А теперь поговорим, как она работает. Вот, что она представляет из себя в версии 2.1.3 :

Где indexOf это вот это:

Забавный комментарий говорит, что так быстрее, чем родной Array.prototype.indexOf() (могу предположить, что из-за отсутствия всех проверок) и предлагает посмотреть тесты производительности.

По сути — это самый первый способ из первой части.

Underscore

_.contains(list, value) — вот такой метод предлагает нам популярная библиотека для работы с коллекциями. То же самое, что и _.include(list, value) .

Использует === для сравнения. Вернёт true , если в list содержится элемент, который мы ищем. Если list является массивом, будет вызван метод indexOf.

Где nativeIndexOf — штука, которая говорит, что Array.prototype.indexOf() существует, а obj.indexOf === nativeIndexOf говорит, что list — массив. Теперь понятно, почему этот метод медленнее, чем jQuery.inArray() , просто обертка над Array.prototype.indexOf() . Ничего интересного.

Lodash

_.includes(collection, target, [fromIndex=0]) — вот последняя надежда на новые мысли, от второй знаменитейшей библиотеки для работы с коллекциями. То же самое, что _.contains() и _.include() .

Возвращает true , если содержит и false если нет. fromIndex индекс элемента, с которого начинаем поиск.

guard — служебный аргумент. Сначала находится длина коллекции, выбирается fromIndex , а потом. нет, не Array.prototype.indexOf() ! Для поиска в строке используется String.prototype.indexOf() , а мы идем дальше в _.getIndexOf() и в результате попадём в ло-дашскую имплементацию indexOf() :

Она интересна тем, что fromIndex может принимать значения как Number , так и Boolean и если это всё таки значение булевого типа и оно равно true , то функция будет использовать бинарный поиск по массиву! Прикольно. Иначе же выполнится indexOf() попроще:

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

Можно предложить просто обернуть _.indexOf() для поиска элемента:

Где fromIndex будет либо индексом откуда начинаем искать, либо true , если мы знаем, что arr отсортирован.

Заключение, хотя и в стиле интермеццо

И да, все эти варианты имеют смысл, только если момент с поиском данных част в вашем алгоритме или поиск происходит на очень больших данных. Вот приведу ниже несколько тестов на поиск элементов типа Number и String в массивах длинной 1000000 (миллион) элементов для трех случаев, когда элемент находится вначале массива, в середине (можно считать за среднюю по палете ситуацию) и в конце (можно считать за время поиска отсутствующего элемента, кроме метода с Array.prototype.lastIndexOf() ).

Результаты тестов могут сильно зависеть от версии браузера, да и от самих браузеров, как этого избежать не знаю, но рекомендую протестить на нескольких.

Видно, что в среднем везде выигрывает первый способ из первой части (написанный собственноручно), а второе место обычно делят lоdash и Array.prototype.includes() .

Да, прошу заметить, что если взбредёт в голову искать NaN , то это может не получиться почти во всех методах, так как NaN !== NaN .

Оцените статью
SoftLast
Добавить комментарий