Комментарии 99
хабрапарсер лох. вот ссылка: j.mp/ch41lh
if (myArray[3] != undefined)
Распространенная ошибка — считать undefined зарезервированным именем:
<script>
var myArray = [];
if (myArray[3] != undefined) {
alert('1: true');
}
var undefined = true;
if (myArray[3] != undefined) {
alert('2: true');
}
</script>
На самом деле всегда нужно делать так:
<script>
var myArray = [];
if (typeof myArray[3] != 'undefined') {
alert('1: true');
}
var undefined = true;
if (typeof myArray[3] != 'undefined') {
alert('2: true');
}
</script>
Да не то, чтобы часто встречалась такая ситуация, когда значение undefined подошло бы :). Следовательно, проверка на значение undefined вполне уместна и без проверки на тип 'undefined '.
undefined не зарезервированное слово, всего лишь глобальная переменная, которая может быть переопределена. Поэтому не следует её использовать, только если в случае вы явно определили её значение в текущем контексте.
И вам ссылочку.
Блин, карму-то успел кто-то испаганить — habrahabr.ru/blogs/javascript/104186/#comment_3252650 (теги не проходят :( ).
честно говоря за несколько лет работы с javascript ниразу не видел чтоб кто-то переопределил undefined
Пока гром не грянет мужик не перекрестится? Ну ничем с точки зрения javascript слово undefined не отличается от, например, antidefined.
с точки зрения языка — нет, а с точки зрения среды в браузере — да. Знаете браузер, где переменная undefined не определена по умолчанию? Знаете браузер, где переменная antidefined определена по умолчанию?
да, есть риск, что кто-то переопределит undefined. Есть такой же риск, что кто-то переопределит setTimeout, Object.prototype и почти любую другую переменную. Просто не используйте такой код и не пишите его сами.
ps: #define TRUE FALSE
да, есть риск, что кто-то переопределит undefined. Есть такой же риск, что кто-то переопределит setTimeout, Object.prototype и почти любую другую переменную. Просто не используйте такой код и не пишите его сами.
ps: #define TRUE FALSE
Я не вижу различия между определенной переменой «неопределенной» (undefined) и неопределенной переменной antidefined. Почему мне следует избегать переопределения именно переменной undefined? Чем код a == undefined отличается от a == antidefined? Почему я не могу использовать второй вариант и не переопределять нигде antidefined?
Ответ на эти вопросы в простом правиле: проверяйте тип, вместо соответствия непонятной переменной и все будет железно работать так, как задумывалось.
Ответ на эти вопросы в простом правиле: проверяйте тип, вместо соответствия непонятной переменной и все будет железно работать так, как задумывалось.
Знаете браузер, где переменная undefined не определена по умолчанию?
IE5 =)
IE5 =)
я вам даже сочувствую, что вы это знаете: )
Спасибо, я справляюсь. =)
Принципиально то на вопрос ответили. Итого, опасность не равна 0. Хотя тут речь скорее о переносимости кода. Ныне, например, развиваются мобильные платформы, а уж чего в них напишут…
Best practice за typeof или (function(undefined){/*code*/})();
Принципиально то на вопрос ответили. Итого, опасность не равна 0. Хотя тут речь скорее о переносимости кода. Ныне, например, развиваются мобильные платформы, а уж чего в них напишут…
Best practice за typeof или (function(undefined){/*code*/})();
В jQuery это красиво так сделано:
(function($, undefined) {
})(jQuery);
Что и рекомендуется делать всем при возможности. Собственно, по 2 причинам.
1. Мы однозначно определяем значение переменной undefined внутри контекста.
2. Как следствие первого, при обращении к undefined не происходит поиска по глобальному контексту, что есть вери-гуд.
1. Мы однозначно определяем значение переменной undefined внутри контекста.
2. Как следствие первого, при обращении к undefined не происходит поиска по глобальному контексту, что есть вери-гуд.
при 'undefined' вообще никакого поиска не происходит.
Здрасте. При отсутствии локальной переменной 'undefined' поиск будет происходить в глобальном контексте, т.к. как уже было сказано, undefined — это всего лишь свойство объекта window.
Да, здравствуйте, 'undefined' — это строка.
А вы шутник :) А ну марш читать спецификацию!
The undefined value is a primitive value used when a variable has not been assigned a value.
The undefined value is a primitive value used when a variable has not been assigned a value.
Вы издеваетесь или не видите кавычки?
Скорее всего, мы говорим про разные ветки дискуссии.
Эта ветка идёт от комментария
(function($, undefined) {
})(jQuery);
Эта ветка идёт от комментария
(function($, undefined) {
})(jQuery);
Как следствие первого, при обращении к undefined не происходит поиска по глобальному контексту, что есть вери-гуд.
при 'undefined' вообще никакого поиска не происходит.
Мы говорим про локальный контекст и переменную undefined, которая в нём определена.
Вы же имели ввиду строку со значением 'undefined' (хотя я не понял, как она относится к этому вопрос, там её нет). В общем, надеюсь мы понимаем сейчас, кто о чём говорит. Вопрос же об использовании именно переменной с именем 'undefined', не typeof == 'undefined'.
Вы же имели ввиду строку со значением 'undefined' (хотя я не понял, как она относится к этому вопрос, там её нет). В общем, надеюсь мы понимаем сейчас, кто о чём говорит. Вопрос же об использовании именно переменной с именем 'undefined', не typeof == 'undefined'.
Что и рекомендуется делать всем при возможности.
Так почему же не использовать строку-то, я вот к чему? Тем более, что оператор typeof строку возвращает.
Методы сравнения значения переменной со значением undefined и определение типа через typeof, который возвращает строку — разные подходы. Вы можете использовать и тот и этот, если точно уверены, что переменная 'undefined' однозначно определена. Мы обсуждали именно использование переменной.
Правда typeof == 'undefined' слегка медленнее, чем сравнение param == undefined, но разница оооочень маленькая.
Правда typeof == 'undefined' слегка медленнее, чем сравнение param == undefined, но разница оооочень маленькая.
вместо
(myArray[3] != undefined) и (typeof myArray[3] != 'undefined')
я использую
(myArray[3] != null)
В чём я не прав?
(myArray[3] != undefined) и (typeof myArray[3] != 'undefined')
я использую
(myArray[3] != null)
В чём я не прав?
лучше всего в данном случае вместо != использовать !==
Про какой конкретный случай вы пишите?
Если автору комментария нужно проверить наличие элемента и одновременно проверить на «пустое» значение, то лучше всего использовать выражение if (myArray[3]) — выполняется быстрее, чем любой из операторов сравнения.
Если нужно сравнить _только_ с undefined и с null, то оптимально использовать if (myArray[3] != null), без сравнения типов операндов — быстрее, чем оператор идентичности !==.
Если автору комментария нужно проверить наличие элемента и одновременно проверить на «пустое» значение, то лучше всего использовать выражение if (myArray[3]) — выполняется быстрее, чем любой из операторов сравнения.
Если нужно сравнить _только_ с undefined и с null, то оптимально использовать if (myArray[3] != null), без сравнения типов операндов — быстрее, чем оператор идентичности !==.
извиняюсь
* пишете
* пишете
первое выдаст ошибку в IE (при отсутствии свойства)
второе — может быть, надо прогнать тесты. Вообще идентичность быстрее работает, если сравниваемые величины не идентичны (чем простое сравнение, это вроде очевидно). И примерно одинаково, если сравнениваемые величины равны.
второе — может быть, надо прогнать тесты. Вообще идентичность быстрее работает, если сравниваемые величины не идентичны (чем простое сравнение, это вроде очевидно). И примерно одинаково, если сравнениваемые величины равны.
Ошибку? Нет, не выдаст. Значение будет undefined. 7 и 8 версии ослика.
Насчет строгого сравнения да, вы правы. Если типы разные, то идентичность быстрее.
Если не разные, то медленнее. Но, опять же, если вы хотите сравнить одновременно с null и с undefined, то нужно использовать !=. Иначе будете сравнивать только с одним из них либо двойное условие.
Насчет строгого сравнения да, вы правы. Если типы разные, то идентичность быстрее.
Если не разные, то медленнее. Но, опять же, если вы хотите сравнить одновременно с null и с undefined, то нужно использовать !=. Иначе будете сравнивать только с одним из них либо двойное условие.
Starting in Javascript 1.8.5 (Firefox 4), undefined is read only, as per the ECMAscript 5 specification.
Продолжайте писать var undefined = 'бла-бла-бла'; и проверять с помощью typeof…
Продолжайте писать var undefined = 'бла-бла-бла'; и проверять с помощью typeof…
как это
var myArray = [4,3,1];
console.info(1 in myArray); // will return 'true'
console.info(3 in myArray); // will return 'false' — разве false?
var myArray = [4,3,1];
console.info(1 in myArray); // will return 'true'
console.info(3 in myArray); // will return 'false' — разве false?
Вы будете просто ошеломлены, узнав, как много других полезных и странно-полезных вещей содержит в себе JS (Ecma). Просто начните читать хорошие мануалы — и много вопросов отпадёт само-собой.
У такой проверки есть одно но: унаследованные свойства и методы также возвращают true:
function Rabbits() {}
var rabbit = new Rabbits();
console.log( 'toString' in rabbit ) // true
function Rabbits() {}
var rabbit = new Rabbits();
console.log( 'toString' in rabbit ) // true
Хочется заметить, что может быть следующая ситуация
var a = [1,2,undefined,3]
и в этом случае не получится проверить через if (a[2] != undeined)
т.к. ключ существует, но значение undefined!
тоже самое и с объектами
a = {b:undefined}
ключ b существует, значение undefined и проверить получится только через in
var a = [1,2,undefined,3]
и в этом случае не получится проверить через if (a[2] != undeined)
т.к. ключ существует, но значение undefined!
тоже самое и с объектами
a = {b:undefined}
ключ b существует, значение undefined и проверить получится только через in
А еще конструкция
if('param' in object)
работает быстрее чем
if(object['param']) или if(object.param)
if('param' in object)
работает быстрее чем
if(object['param']) или if(object.param)
Точно, засекали? =)
На глаз заметно при больших объёмах данных :)
Вот небольшой тестик
И результат запущенного кода в консоле Firefox 4
test: 38697ms
test: 2008ms
console.time('test');
for(var i=0;i<10000000;++i)
if(window['clearTimeout']);
console.timeEnd('test');
console.time('test');
for(var i=0;i<10000000;++i)
if('setTimeout' in window);
console.timeEnd('test');
И результат запущенного кода в консоле Firefox 4
test: 38697ms
test: 2008ms
Ваш тест не совсем верный.
Вы тестируете на глобальном контексте, результаты на нём очень сильно отличаются от результатов на объектах. Да и пример не жизненный, подобного юзкейза я не могу придумать на глобальном контексте, разве что для теста только.
Попробуйте, например, продублировать все поля объекта window в какую-нибудь локальную переменную и запустите свой тест ещё раз. Вы увидите, что, мало того, что результаты почти не оличаются, так in оператор еще и работает чуть медленнее.
Хотя работа in оператора осуществляется через HasProperty() с доп. проверками перед этим, конкретную реализацию которой в браузерах я не знаю. И назначение in оператора всё же несколько иное, чем array[key], который возвращает false в случаях пустой строки, нуля, false и null.
Вы тестируете на глобальном контексте, результаты на нём очень сильно отличаются от результатов на объектах. Да и пример не жизненный, подобного юзкейза я не могу придумать на глобальном контексте, разве что для теста только.
Попробуйте, например, продублировать все поля объекта window в какую-нибудь локальную переменную и запустите свой тест ещё раз. Вы увидите, что, мало того, что результаты почти не оличаются, так in оператор еще и работает чуть медленнее.
Хотя работа in оператора осуществляется через HasProperty() с доп. проверками перед этим, конкретную реализацию которой в браузерах я не знаю. И назначение in оператора всё же несколько иное, чем array[key], который возвращает false в случаях пустой строки, нуля, false и null.
эм, вот только если в object['param'] будет false или 0 или что то подобное,. то всё как то печально станет, не находите?
Это зависит от задачи, не находите ли?
Если нужно проверит на существование свойства то нужно использовать in.
Если нужно проверить на положительный результат то in не подходит но все равно if('param' in object && object['param']) будет быстрей с учетом конечно если много не определенных свойств.
И опять же нужно ли это использовать нужно смотреть по обстоятельствам.
Если нужно проверит на существование свойства то нужно использовать in.
Если нужно проверить на положительный результат то in не подходит но все равно if('param' in object && object['param']) будет быстрей с учетом конечно если много не определенных свойств.
И опять же нужно ли это использовать нужно смотреть по обстоятельствам.
А вот здесь вы совсем не правы. Двойная проверка ни к чему, она замедлит выполнение двоекратно.
Не верите? Протестируйте.
Не верите? Протестируйте.
Я же уточнил если большинство не определенных свойств. Ну а в жизни конечно не видел таких обстоятельств. Это я сказал как интересный факт не более того :)
Что значит «неопределённых»? if (object['param']) — вполне достаточно, чтобы покрыть все false-значения, включая undefined (несуществующее в объекте)
А не что 0 это тоже значение, и оно иногда нужное :)
В общем спор не о чем
В общем спор не о чем
Извините, но вы, по-моему, не понимаете сути.
Выполняя двойную проверку if ('param' in object && object['param']) результат абсолютно аналогичный if (object['param']). Это как написать: if (3 > -1 && 3 >=0)
Выполняя двойную проверку if ('param' in object && object['param']) результат абсолютно аналогичный if (object['param']). Это как написать: if (3 > -1 && 3 >=0)
Хорошо вот вам еще один тест
Результаты
test: 1408ms
test: 592ms
console.time('test');
for(var i=0;i<100000;++i)
if(window['test'] );
console.timeEnd('test');
console.time('test');
for(var i=0;i<100000;++i)
if('test' in window && window['test']);
console.timeEnd('test');
Результаты
test: 1408ms
test: 592ms
>>Это зависит от задачи, не находите ли?
а название топика не на что не наводит?
а название топика не на что не наводит?
if(object['param']) или if(object.param)
В этом случае проиcходит целый ряд проверок в зависимости от типа и значения param. Если param = (number)0, (boolean)false, undefined, null, (string)'' — то будет false, в остальных случаях true
Поэтому этот метод медленнее.
Было бы правильнее сравнивать производительность if('param' in object) и if(typeof object.param != 'undefined') или hasOwnProperty
вы пердпологаете что получение типа объекта и сравнение его с со строкой будет быстрей?
По моему тут и так ясно что быстрей выполняется и без тестов :)
По моему тут и так ясно что быстрей выполняется и без тестов :)
Дело ваше, хозяйское. Просто сравнивать с заведомо медленной проверкой — странный эксперимент, вот что я хотел сказать.
т.е. этот вариант заведомо быстрый? раз вы предлагаете с ним сравнивать )))))
В нем происходит минимум операций, в отличии от if(object.param). Прежде чем сравнивать производительность, не мешало бы провести оптимизацию проверки if(object.param) и это
if(typeof object.param != 'ненужный тип')
или
if(typeof object.param == 'нужный тип')
так доступнее объяснил?
ОК держите тест :)
Результат
test: 517ms
test: 84ms
test: 529ms
console.time('test');
for(var i=0;i<100000;++i) if(window['setTimeout']); console.timeEnd('test');
console.time('test');
for(var i=0;i<100000;++i) if('setTimeout' in window); console.timeEnd('test');
console.time('test');
for(var i=0;i<100000;++i) if('undefined' == typeof window['setTimeout']); console.timeEnd('test');
Результат
test: 517ms
test: 84ms
test: 529ms
Контр-пример.
obj.param: 1256ms
typeof obj.param == «number»: 1063ms
«test» in obj: 1180ms
Как видите typeof obj.param быстрее obj.param
Однако очевидно, что в разных условиях производительность разная. А значит любые утверждения тут невозможны :)
obj.param: 1256ms
typeof obj.param == «number»: 1063ms
«test» in obj: 1180ms
Как видите typeof obj.param быстрее obj.param
Однако очевидно, что в разных условиях производительность разная. А значит любые утверждения тут невозможны :)
var obj = { test: 1 }
console.time('obj.param');
for(var i=0;i<10000000;++i)
if(obj['test']);
console.timeEnd('obj.param');
console.time('typeof obj.param == «number»');
for(var i=0;i<10000000;++i)
if(typeof obj['test'] == 'number');
console.timeEnd('typeof obj.param == «number»');
console.time('«test» in obj');
for(var i=0;i<10000000;++i)
if('test' in obj);
console.timeEnd('«test» in obj');
Чтобы проверить на «пустое» значение, использование if (obj.param) оптимальнее, чем typeof.
Зачем спорить, когда можно почитать спецификацию, как именно делается проверка, шаг-за-шагом и проверить на практике тестом.
2no_smoking: вы как проверяли на глобальном контексте, так проверяете. Неверно это, поймите.
Зачем спорить, когда можно почитать спецификацию, как именно делается проверка, шаг-за-шагом и проверить на практике тестом.
2no_smoking: вы как проверяли на глобальном контексте, так проверяете. Неверно это, поймите.
Тут то речь не про пустое, а про отсутствующее.
З.Ы. Кроме того, явно указывая в проверке чего мы хотим, повышает читаемость кода. Ну это уже каждому свое.
З.Ы. Кроме того, явно указывая в проверке чего мы хотим, повышает читаемость кода. Ну это уже каждому свое.
«О, сколько нам открытий чудных
Готовят просвещенья дух,
И опыт, сын ошибок трудных,
И гений, парадоксов друг,
И случай, бог изобретатель.»
А. С. Пушкин
Готовят просвещенья дух,
И опыт, сын ошибок трудных,
И гений, парадоксов друг,
И случай, бог изобретатель.»
А. С. Пушкин
т.е. наличие любой глобальной переменной можно поверять как if ('someName' in window)?
Стоило еще написать, что для итерации по массивам использовать in нельзя.
Вот это — ошибка в большинстве случаев:
т.к. будет пробегаться не только по элементам массива, но и по его свойствам (которые не built-in).
Вот это — ошибка в большинстве случаев:
for (x in [1,2,3]){
}
т.к. будет пробегаться не только по элементам массива, но и по его свойствам (которые не built-in).
это я к чему — что использовать in для итерации по массивам как раз и нельзя
Да, будет ошибка. Но in использовать иногда удобно.
С такой проверкой и безопасно и смотрится довольно не плохо.
for(var i in obj) if(obj.hasOwnProperty(i)) {
// some work
}
С такой проверкой и безопасно и смотрится довольно не плохо.
НЛО прилетело и опубликовало эту надпись здесь
как прервать итерацию на середине?
ну, например, так:
fn.call(...)
if (fn.call(...) === false) return;
[1,2,3].forEach(function(element, index) {
if (index === 2) return false;
});
>> как прервать итерацию на середине?
Использовать every или some, а не forEach.
Использовать every или some, а не forEach.
break или continue
хотя не рекомендуют, но в случае вложенных массивов удобней и работает быстрее.
хотя не рекомендуют, но в случае вложенных массивов удобней и работает быстрее.
Учите мат. часть — это же и так очевидные вещи, зачем про них на Хабре писать?
Флэнагана почитайте и пишите то, что может быть действительно интересно, а не прописные истины…
Флэнагана почитайте и пишите то, что может быть действительно интересно, а не прописные истины…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Проверка существования свойств и методов объекта в Javascript