Вызов typeof
возвращает строку, содержащую информацию о типе операнда.
Оператор typeof
используется в двух формах:
- typeof operand
- typeof (operand)
Эти формы идентичны: можно использовать скобки, а можно и не использовать - работает одинаково.
Оператор возвращает тип в виде строки, например:
var a = 5
alert(typeof a) // "number"
var a = 'test'
alert(typeof a) // "string"
Тип typeof
возвращается, исходя из следующей таблицы соответствия типам javascript:
Тип |
Результат |
Undefined |
"undefined" |
Null |
"object" |
Boolean |
"boolean" |
Number |
"number" |
String |
"string" |
Function |
"function" |
Любой другой объект |
"object" |
Часто возникают вопросы - почему и зачем таблица именно такая? Ответ простой: потому что так получилось по ходу развития javascript.
В старом javascript-коде можно увидеть применение typeof
для проверки существования переменной:
if (typeof(var) == "undefined") { ... }
В современном javascript лучше писать:
if (window.var !== undefined) { ... }
или, зачастую, подойдет и просто:
if (window.var) { ... }
P.S. Использовать просто if(var)
нельзя, так как доступ к неопределенной переменной вызовет ошибку. Ну а обращение к отсутствующему свойству глобального объекта window всего лишь вернет undefined
Кроме того, оператор typeof
используется для полиморфизма. Например, следующая функция получает узел DOM или ID узла и в обоих случаях корректно прячет узел.
function hideNode(node) {
if (typeof node == 'string') {
node = document.getElementById(node)
}
node.style.display = 'none'
}
>>можно писать:
Думаю что так писать не стоит. Вот пример, когда этот метод не сработает:
Никто в здравом уме не будет переопределять
undefined
во что-либо другое.Думаю что на здравый ум полагаться не стоит, а потому, надежной проверкой будет проверка при помощи typeof.
Забавный комментарий. На чей здравый ум не стоит полагаться? На свой или на чужой?
Конечно же на чужой . Ведь в большинстве случаев я использую сторонние библиотеки.
if (window.var !== undefined) { ... }
без объявленной переменной undefined вы сравниваете одну несуществующую переменной с другой;) сравнивать нужно со строкой "undefined" (в кавычках!!!), так что проблемы с объявлением переменной undefined никакой нет!!!
Как то вы объясняете плохо. Пока в другом месте не нашел непонятно.
Операция typeof возвращает строку, содержащую информацию о типе операнда. Она имеет вид:
typeof expr или typeof(expr)
где expr — любое выражение. Возвращаемое значение может быть одной из шести строк: "number" (число), "string" (строка), "boolean" (логическое значение), "object" (объект), "function" (функция) или "undefined" (неопределенное значение). Примеры:
var size = 1;
var shape = "круглый";
var today = new Date();
typeof(size); // возвращает "number"
typeof shape; // возвращает "string"
typeof today; // возвращает "object"
Вообще, по смысловой нагрузке, проверка существования переменной в объекте переменных, либо, что эта переменная имеет значение undefined, может быть осуществлена либо через:
либо (в глобальной области) с помощью оператора in:
Опять же, проверка с typeof позволяет проверить наличие переменной и во вложенном контексте (например, в функции), чего нельзя сделать при помощи window.var или window.var !== undefined. Более того, в предпоследнем случае, объект может иметь значение false, что полностью меняет смысл проверки.
Поэтому, typeof вполне себе используется в современном ES.
Теоретически да,
typeof
может проверить наличие переменной в текущем контексте.Однако, в реальных приложениях на современном(да и на несовременном тоже) javascript этого не нужно.
Локальная переменная, объявленная при помощи var, не нуждается в
typeof
: достаточно простогоif (myVar !== undefined)
.Поэтому для проверки на
undefined
операторtypeof
в современном javascript не используется.Т.е. предлагаете делать две проверки на существование переменной в контекстах?
А вы не знаете, что творится в локальном контексте вашей функции? Если у вас есть переменная в локальном контексте - проверяйте её без typeof, если нету, то зачем её вообще проверять?
А если я хочу проверить является ли переменная именно целым числом, то никак?? что мне, циклом разбивать его и проверять каждый символ? //
Давычо?!
Мы проверяем не на четность / нечетность, а на целость / дробность.
комментаторов выше в топку.
type==undefined работает далеко не всегда, особенно в ИЕ.
не приходилось видеть сообщение undefined is undefined? ))
приходится использовать конструкцию
if (typeof myvar == 'undefined' || typeof myvar=='null' || typeof myvar=='unknown') {
Что еще за typeof myvar=='null'?
Проверил, в ИЕ работает.
Это для отладки в Firefox Firebug. После отладки функции можно не закоментирововать и не удалять. Можна готовую работу заказщику отправлять.
Лучше так
Number.MIN_VALUE > 0; // true or false?
typeof null; // what type?
null === Object; // true or false?
// и самый сок
NaN === NaN; // true or false?
typeof NaN; // what type?
Number.MIN_VALUE > 0; // true
/*
Дело в том, что MIN_VALUE это наименьшее число, БОЛЬШЕ НУЛЯ
*/
typeof null; // object
null === Object; // false
/*
null, хоть и имеет тип "object", не является Object'ом
*/
NaN === NaN; // false
/*
Впечатляет, да? Я не могу найти этому объяснения. Автор же просто предполагает, что некоторые люди любят иногда понюхать клей...
*/
typeof NaN; // number
/*
Вот это сильно. Если вдруг кто не помнит, NaN — not a number.
*/
NaN === NaN; // false
Логически всё верно. NotaNumber1 = object1. NotaNumber2 = object2. object1 != object2. следовательно, NaN != NaN ни при каких обстоятельствах.
typeof null; // object
null === Object; // false
/*
null, хоть и имеет тип "object", не является Object'ом
*/
В том, что ключевое слово null не равняется ссылке на конструктор объекта, есть что-то неожиданное или неправильное?
'blabla' === String тоже вернет false, и что?
Number.MIN_VALUE > 0; // true
/*
Хотя бы попробовал вывести это число сначала. Это наименьшее число, в смысле по модулю, оно хоть и очень маленькое, но всё же больше нуля.
*/
NaN === NaN; // false
/*
А по твоему должно быть иначе:
Math.sqrt(-1) === (+"Not a Number"); //true или false? я думаю false
*/
typeof NaN; // number
/*
NaN - это специфичное значение Number, посмотри напр в википедии.
Используется вместо генерации исключения, когда значение не удаётся посчитать, напр Math.sqrt(-1), 0/0. Есть и другие специфичные значения у Number, например Infinity. И это логично: что мы получим разделив число на число, пожалуй, число, а число на число 0 - тоже число, только это число Infinity (бесконечность) (но 0/0 == NaN), можно взять арктангенc Infinity и будет 90 град.
*/
опасный способ. всё время нужно думать о том, что var может быть определена, но кастоваться в false. имхо, это стоит добавить в статью.
а мне прикольно typeof() использовать
По поводу typeOf: весьма полезная штука, спасала не раз и не два.
Особенно в случаях когда используешь сторонние JS модули, написанные любителями быстрых но недальновидных решений. Типа этого:
...
Array.prototype.indexOfObjWithItem = function (name, item, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i][name] === item) return i;
}
return -1;
};
...
После чего предлагаю подумать что произойдет в цикле ниже:
var arr = [], str = "";
arr.a = { val: function () { return 1 } }
arr.b = { val: function () { return 2 } }
for (item in arr) {
str += arr[item].val() + ",";
}
лечится например так:
if (typeof item == "function") continue;
а что, если Global - не window, как, например, в node.js или любой другой не-браузерной среде? В таком случае typeof someVar != 'undefined' будет работать, а someVar != undefined выкинет ReferenceError
Итого, typeof someVar != 'undefined' просто безопаснее и "кроссплатформеннее", т.к. typeof не пытается брать значения операнда, а сразу возвращает "undefined", если свойство с таким именем не найдено. См. production:
------------
if Type(val) is Reference, then
If IsUnresolvableReference(val) is true, return "undefined".
------------
На сайте youtube.com код
вызывается в глобальной области видимости. Почему это работает (если это работает)? yt проверяется без window и код на этом должен прекратить выполняться.
И для чего используется
вместо
?
По поводу var yt = yt || {}. Дело в том, что JavaScript очень коварный язык. Он лишь кажется простым. На деле же он является одним из самых сложных для понимания. В данном случае код работает из-за особенности обработки директивы var. Все директивы var обрабатываются на входе в процедуру, не зависимо от того в каком месте этой процедуры они написаны. Иными словами
Эквивалентно
Получается yt как бы была объявлена до этой проверки. Потому и нет ошибки. Хотя я бы не стал так делать, ибо не наглядно и может стать причиной косяков.
Более того, у этой особенности языка есть неприятные подводные камни. Так, если вверху процедуры вы попытаетесь использовать глобальную переменную
а потом внизу этой же процедуры объявите локальную переменную
То получится что пятерку вы ранее присваивали локальной переменной, а не глобальной. Глобальная же переменная при этом становится недоступна в пределах всей процедуры. Потому что, например:
Это На самом деле:
При желании вы вообще можете объявить все локальные переменные в самом низу, при этом они будут доступны, так словно вы объявили их вверху. Это ни в коем случае не стоит расценивать как рекомендацию. Наоборот, я бы рекомендовал, подобного всячески избегать.
Ну и напоследок комплексный пример:
Ну а что касается swf, то предположу что автору этого кода просто нравится писать в таком стиле. Кроме того, обычно использовать прямое присвоение полям класса какого-либо числового или строкового значения считается плохим тоном. Такие числа и строки называют "магическими", потому что из контекста программы может быть не очевидно, что они значат, и почему они именно такие. Вместо них, как правило, используются именованные константы. Но в JavaScript нету констант. Поэтому приходится использовать переменные. Так, вместо того, чтобы присвоить innerHTML три точки, здесь этим трем точкам дано имя swf, что как бы подразумевает что в этом месте должен располагаться флеш объект. Это, пусть и не очень емкая, но хоть какая-то подсказка. Так в коде проще разобраться. А если одно и то же значение в коде используется несколько раз, то тогда уж тем более лучше его переменной присвоить. В случае с JavaScript, есть и еще одна причина. К JS коду часто применяют минификацию, чтобы сделать код компактней. При этом минификатор работает по определенному алгоритму, и часто код пишется так, чтобы минификатор его наиболее оптимально обработал. Если написать код, в котором неоднократно используется одно и то же значение, то минификатор никак не сможет его сжать, а если присвоить это значение переменной, и потом использовать ее, то даже если имя переменной длинное и информативное, минификатор может просто изменить его на одну букву, если эта переменная локальная. В связи со всем этим, и может чем-то еще, во многих программистских коллективах существуют соглашения по написанию кода, часто они есть не только на словах, но даже в виде документа. Это особенно важно при совместной работе над одним проектом нескольких человек. Данный, на вид избыточный код может быть следствием такого соглашения.
В данном случае этот код может казаться избыточным, но во-первых если уж разработчик придерживается определенного стиля или тем более соглашения, то лучше придерживаться его во всем, даже когда это кажется излишним, во-вторых любая функция в дальнейшем может быть модифицирована, дополнена, и лучше изначально писать код с запасом на будущее.
Cryvage, а запускать-то функцию кто будет?
Объясните пожалуйста, кто-нибудь, как может typeof == 'source' ?
Это рабочая, рекурсивная функция для клонирования объектов, но не понимаю, откуда 'source', даже учитывая == вместо ===
А эта функция и не работает. Попробуйте выполнить вот этот код:
Из него можно понять, что внутненний объект не клонируется. А проблема, видимо, в том, что агрумент функции был переименован из object в source, что повело за собой и замену строки "object" на "source".
Таким образом правильный вариант такой:
Как-то Вы странно объясняете ...
"typeof source[i] == 'object'" - это и ежу понятно что нет такого типа как "source", тогда зачем парить народ, приводя в начале нерабочий вариант, а потом раскрывать суть?
Может стоит сразу писать правильно, но тогда пропадает сама "суть" и мы приходим к выводу, что так делать не стоит.
Чет я с просони неправильно понял и потерялся в дискуссии. Так что извиняюсь.
В общем, претензии отзываются, но все просто как я и говорил выше - нет такого типа как "source" и все правильно - имелся ввиду "object", но все-равно непонятно - какого черта там "source"?!
А как проверить на существование такого объекта:
config.showcase.timer
Следующая запись вызывает ошибку:
if(window.config.showcase.timer === undefined)
В таком случае употребление typeof не поможет, выдаст такую же ошибку, по причине того, что config не был определён.
Убеждаемся в этом:
Правильный код (как я считаю):
Смысл этого кода в том, что нужно проверить существует ли основной (родительский объект), а потом проверять вложенные свойства.
Ведь, всё это нужно, чтобы наш код не вернул ошибку. Этот код и обходит эту ошибку.
Если свойство определено, то всё будет отлично, пример:
Почему ответ - number?
Оператор typeof возвращает строку, указывающую тип операнда. Он может использоваться в двух формах:
typeof operand
typeof (operand)
Обе формы эквивалентны: использование скобок необязательно, и результат будет одинаковым.