Некоторые другие возможности
Различные возможности JavaScript, которые достаточно важны, но не заслужили отдельного раздела.
Типы данных: [[Class]], instanceof и утки
Время от времени бывает удобно создавать так называемые «полиморфные» функции, то есть такие, которые по‑разному обрабатывают аргументы, в зависимости от их типа. Например, функция вывода может по‑разному форматировать числа и даты.
Для реализации такой возможности нужен способ определить тип переменной.
Оператор typeof
Мы уже знакомы с простейшим способом – оператором typeof.
Оператор typeof надежно работает с примитивными типами, кроме null , а также с функциями. Он возвращает для них тип в виде строки:
alert( typeof 1 ); // 'number' alert( typeof true ); // 'boolean' alert( typeof "Текст" ); // 'string' alert( typeof undefined ); // 'undefined'
alert( typeof null ); // 'object' (ошибка в языке) alert( typeof alert ); // 'function'
…Но все объекты, включая массивы и даты для typeof – на одно лицо, они имеют один тип 'object' :
alert( typeof {} ); // 'object' alert( typeof [] ); // 'object' alert( typeof new Date ); // 'object'
Поэтому различить их при помощи typeof нельзя, и в этом его основной недостаток.
Секретное свойство [[Class]]
Для встроенных объектов есть одна «секретная» возможность узнать их тип, которая связана с методом toString .
Во всех встроенных объектах есть специальное свойство [[Class]] , в котором хранится информация о его типе или конструкторе.
Оно взято в квадратные скобки, так как это свойство – внутреннее. Явно получить его нельзя, но можно прочитать его «в обход», воспользовавшись методом toString стандартного объекта Object .
Его внутренняя реализация выводит [[Class]] в небольшом обрамлении, как "[object значение]" . Например:
var toString = {}.toString;
var arr = [1, 2];
alert( toString.call(arr) ); // [object Array]
var date = new Date;
alert( toString.call(date) ); // [object Date]
var user = { name: "Вася" };
alert( toString.call(user) ); // [object Object]
В первой строке мы взяли метод toString , принадлежащий именно стандартному объекту {} . Нам пришлось это сделать, так как у Date и Array – свои собственные методы toString , которые работают иначе.
Затем мы вызываем этот toString в контексте нужного объекта obj , и он возвращает его внутреннее, невидимое другими способами, свойство
[[Class]] .
Для получения [[Class]] нужна именно внутренняя реализация toString стандартного объекта Object , другая не подойдёт.
К счастью, методы в JavaScript – это всего лишь функции‑свойства объекта, которые можно скопировать в переменную и применить на другом объекте через call/apply . Что мы и делаем для {}.toString .
Метод также можно использовать с примитивами:
alert( {}.toString.call(123) ); // [object Number] alert( {}.toString.call("строка") ); // [object String]
Для большего удобства можно сделать функцию getClass , которая будет возвращать только сам [[Class]] :
function getClass(obj) {
return {}.toString.call(obj).slice(8, ‐1);
}
alert( getClass(new Date) ); // Date alert( getClass([1, 2, 3]) ); // Array
Заметим, что свойство [[Class]] есть и доступно для чтения указанным способом – у всех встроенных объектов. Но его нет у объектов, которые создают наши функции. Точнее, оно есть, но равно всегда "Object" .
Например:
function User() {} var user = new User();
alert( {}.toString.call(user) ); // [object Object], не [object User]
Поэтому узнать тип таким образом можно только для встроенных объектов.
Do'stlaringiz bilan baham: |