В 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
будет истинным в показанном вами литерале объекта примера, потому что у объекта действительно есть свойство, даже если значение свойства равно нулю. Вы не должны иметь свойство вообще , чтобы in мог вернуть 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
, вы бы получили ложные срабатывания (так как это свойства, которые получают почти все объекты из * 1058) *). В браузере с поддержкой ES5 вы можете избежать этой проблемы, создав свой объект с прототипом null
: var corporatePlan = Object.create(null);
Возможно, потому что он проверяет прототипы, оператор in
на некоторых двигателях удивительно медленно .
Обе эти проблемы можно решить с помощью hasOwnProperty
вместо:
console.log(corporatePlan.hasOwnProperty("canSummonKraken")); // true
console.log(corporatePlan.hasOwnProperty("canDismissKraken")); // false
Можно подумать, что оператор будет быстрее, чем вызов метода, но оказывается, что это не совсем верно для кросс-браузера.
Метод флагов:
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
. (Но см. Мой вступительный абзац: Test in your environment. :-))