Ответ 1
В JavaScript вы обычно имеете дело с широким спектром реализаций (если вы не используете его в контролируемой среде, такой как сервер, на котором вы выбираете движок), и поэтому ответ на конкретные вопросы производительности, как правило, "это зависит, проверьте его на двигателях, которые вы собираетесь использовать". Что быстрее всего на одной реализации может быть медленнее на другой, и т.д. http://jsperf.com удобен для такого рода вещей.
Тем не менее, я ожидаю, что in
станет явным победителем здесь. Array#indexOf
должен получить доступ к индексам массива в поиске, а индексы массива - это свойства, подобные любому другому свойству. Поэтому, обращаясь к индексу массива 0
, чтобы узнать, требует ли требуемая строка для поиска 0
, как и для другого, требуется поиск свойства "canSummonKraken"
(а затем он должен выполнить сравнение строк после этого). (Да, индексы массива являются свойствами. Массивы в JavaScript вообще не являются массивами. И indexOf
может потребоваться доступ к нескольким свойствам во время его поиск, тогда как in
будет иметь доступ только к нему. Но, опять же, вам нужно проверить это в своих целевых средах, чтобы убедиться, что некоторые реализации могут оптимизировать массивы, которые имеют смежные диапазоны индексов (но самые медленные из них определенно не делают, и, конечно, если вы беспокоитесь о скорости, вы "беспокоится о том, что самое быстрое на самых медленных двигателях, например, в IE).
Также обратите внимание, что не все механизмы JavaScript даже имеют Array#indexOf
. Большинство из них, но есть еще несколько старых, которые пинают (я смотрю на вас, Microsoft), которые этого не делают.
У вас также есть вопрос, следует ли использовать in
или hasOwnProperty
. Использование in
имеет то преимущество, что это оператор, а не вызов функции; использование hasOwnProperty
имеет то преимущество, что оно будет рассматривать только конкретный экземпляр объекта, а не его прототип (и его прототип и т.д.). Если у вас не очень унаследованная иерархия (а вы не в своем примере), я ставлю на победу in
, но полезно помнить, что она проверяет иерархию.
Кроме того, помните, что "canSummonKraken" in obj
будет истинным в примере объекта, который вы показали, потому что объект имеет свойство, даже если значение свойства равно null. У вас не должно быть свойство для возврата false. (Вместо in
вы можете просто использовать true и false и искать его как obj.canSummonKraken
.)
Итак, ваши варианты:
-
Ваш метод массива:
corporatePlan = [ 'canDeAuthorize', 'hasGmailSupport', 'canShareReports', 'canSummonKraken', 'etc' ]; console.log(corporatePlan.indexOf("canSummonKraken") >= 0); // true console.log(corporatePlan.indexOf("canDismissKraken") >= 0); // false
... который я бы не рекомендовал.
-
Метод
in
:corporatePlan = { 'canDeAuthorize' : null, 'hasGmailSupport' : null, 'canShareReports' : null, 'canSummonKraken' : null, 'etc' : null }; console.log("canSummonKraken" in corporatePlan); // true console.log("canDismissKraken" in corporatePlan); // false
Вероятно, быстрее, чем
indexOf
, но я бы его протестировал. Полезно, если список может быть очень длинным, и если у вас будет много таких объектов, потому что это требует только того, чтобы свойства "правдивые" существовали вообще. Пустой объект представляет собой план, в котором пользователь ничего не может сделать, и он довольно мал.Здесь я должен отметить две вещи:
-
in
также проверяет прототип объекта, поэтому, если у вас есть такие настройки, какtoString
илиvalueOf
, вы получите ложные срабатывания (так как это свойства, которые почти все объекты получают отObject.prototype
). В браузере с поддержкой ES5 вы можете избежать этой проблемы, создав свой объект прототипомnull
:var corporatePlan = Object.create(null);
-
Возможно, потому, что он проверяет прототипы, оператор
in
на некоторых двигателях неожиданно медленный.
Обе эти проблемы могут быть решены с помощью
hasOwnProperty
вместо:console.log(corporatePlan.hasOwnProperty("canSummonKraken")); // true console.log(corporatePlan.hasOwnProperty("canDismissKraken")); // false
Можно было бы подумать, что оператор будет быстрее, чем вызов метода, но оказывается, что ненадежный истинный кросс-браузер.
-
-
Метод flags:
corporatePlan = { 'canDeAuthorize' : true, 'hasGmailSupport' : true, 'canShareReports' : true, 'canSummonKraken' : true, 'canDismissKraken' : false, 'etc' : true }; console.log(corporatePlan.canSummonKraken); // "true" console.log(corporatePlan.canDismissKraken); // "false" // or using bracketed notation, in case you need to test this // dynamically console.log(corporatePlan["canSummonKraken"]); // "true" console.log(corporatePlan["canDismissKraken"]); // "false" // example dynamic check: var item; item = "canSummonKraken"; console.log(corporatePlan[item]); // "true" item = "canDismissKraken"; console.log(corporatePlan[item]); // "false"
..., что было бы довольно обычным способом, вероятно, быстрее, чем
in
, и, вероятно, по крайней мере так же быстро, какhasOwnProperty
. (Но см. Мой вступительный абзац: Тест в вашей среде.:-))