Неформальное определение: тип - внутренняя встроенная характеристика, которая позволяет определить некоторое значение и однозначно отличать его от прочих значений как движку, так и разработчику. Например, если и разработчик и движок трактуют значение 42 иначе, чем "42", эти значения относятся к разным типам.
Важно! Переменные не имеют типа. Его имеют только значения, которые содержат эти переменные.
typeof - встроенный оператор языка, возвращающий строку, содержащую название типа. Определяется тип значения (value) той конструкции, которую передали оператору (это может быть переменная, выражение или примитив).
1. Объекты (typeof {}; // > object)
Важно! Массивы и функции являются разновидностями объектов ( typeof [] === "object" ) с особыми свойствами. Функции могут исполняться (благодаря внутреннему свойств [[Call]], содержащему код функции), массивы имеют целочисленные свойства и автоматически изменяемое свойство length.
2. Строковые литералы (typeof "abc"; // > string)
3. Числа (все - с плавающей точкой двойной точности, typeof 123; // > number)
4. Булевские значения - true, false (typeof true; // > boolean)
Специальные значения:
5. undefined - значение по умолчанию, предопределенная переменная, назначается автоматически, неожиданно отсутствующие данные, в том месте, где они предполагаются (type of undefined; // undefined).
Получается следующим образом:
- Значение переменной по умолчанию (объявление без присвоения).
- Обращение к несуществующему свойству объекта или отсутствующему элементу массива.
- Обращение к отсутствующему аргументу функции.
- Результат выполнения функции без оператора return или с оператором return без параметра.
- Результат использования оператора void expr;
Важно! Фактические могут находиться в двух состояниях - undefined (переменная объявлена, но не имеет значения) и uneclared (переменная не объявлена). Обращение к переменной в состоянии undefined не вызывает ошибки (вернётся undefined), а в состоянии undeclared вызывает ReferenceError. Проблема заключается в том, что typeof для обоих состояний возвращает undefined (причём без ошибки для необъявленных переменных).
6. null - намеренно отсутствующие данные в том месте, в котором они предполагаются, фактически - оператор, однако typeof null === "object". Это известная ошибка языка (фактически должна возвращаться строка "null"), однако она вряд ли будет исправлена.
Объекту, который перестали использовать, лучше сразу присваивать значение null, чтобы освобождать память и не вызывать дополнительно GC и чтобы вылавливать ошибки с повторным обращением к объекту, которых не должно быть.
7. Стандарт ES6 вводит также тип Symbol. ( typeof Symbol() === "symbol" )
Объекту, который перестали использовать, лучше сразу присваивать значение null, чтобы освобождать память и не вызывать дополнительно GC и чтобы вылавливать ошибки с повторным обращением к объекту, которых не должно быть.
7. Стандарт ES6 вводит также тип Symbol. ( typeof Symbol() === "symbol" )
Встроенные объекты языка:
String - обёртка для string
typeof "abc"; //"string"typeof String("abc"); //"string"typeof new String("abc"); //"object"typeof (new String("abc")).valueOf(); //"string"
typeof 123; //"number"typeof Number(123); //"number"typeof new Number(123); //"object"typeof (new Number(123)).valueOf(); //"number"Boolean - обёртка для boolean
typeof true; //"boolean"typeof Boolean(true); //"boolean"typeof new Boolean(true); //"object"typeof (new Boolean(true)).valueOf(); //"boolean"Прочие встроенные объекты:
Array // var a = new Array или var a = [];
Date Function // var f = new Function() или var f = function() {};
RegExp // var s = new Regexp(/\s*/) или var r = /\s*/;
Math
JSON
Object // var o = new Object или var o = {};
Error
Важно! Объект является базовым типом языка, использование оператора new всегда возвращает объект. Примитивы были введены с целью повышения скорости работы движка. Только объекты имеют свойства и методы. При обращении к методам примитивов (причем только числовых, строковых и логических) они временно приводятся к объектам и методы корректно исполняются. Однако попытки присвоить значения свойствам примитивов ничего не дают - в дальнейшем эти свойства возвращают undefined.
Обращение к свойствам и методам значений unedifned и null (или переменных, содержащих эти значения) вызовет ошибку TypeError.
Каждый объект имеет два внутренних свойства-метода valueOf() и toString(), которые могут быть переопределены. Они неявно вызываются при использовании объекта (или ссылки на него), valueOf() при использовании в числовом контексте (арифметические операции с объектами), toString() - в строковом.
Примитивы можно сравнивать напрямую, в отличие от объектов они не имеют внутреннего идентификатора и представляются только своим значением. Объекты сравниваются по ссылке, поэтому два объекта с одинаковыми полями не равны друг другу:
var a = { x: 10 }
var b = { x: 10 }
var c = a;
console.log(a == b); // false
console.log(a === b); // false
console.log(a == c); // true
console.log(a === c); // true
typeof возвращает "object" для всех типов кроме Function, Object и Error, для которых возвращается "function".
Единственный способ избежать ReferenceError для необъявленной переменной - предварительно использовать typeof переменная (вернет "undefined"). При этом реально переменная является undeclared.
value instanceof Constructor
эквивалентно
Constructor.protoptype.isPrototypeOf(value)
Следующая функция возвращает более конкретный тип для каждого объекта, включая встроенные:
var toType = function(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()}toType({a: 4}); //"object"toType([1, 2, 3]); //"array"toType(null); //"null"toType(undefined); //"undefined"(function() {console.log(toType(arguments))})(); //argumentstoType(new ReferenceError); //"error"toType(new Date); //"date"toType(/a-z/); //"regexp"toType(Math); //"math"toType(JSON); //"json"toType(new Number(4)); //"number"toType(new String("abc")); //"string"toType(new Boolean(true)); //"boolean"
Однако возможны нюансы при работе с хост-объектами, которые создаются браузерами и не подчиняются стандарту:
toType(window);//"global" (Chrome) "domwindow" (Safari) "window" (FF/IE9) "object" (IE7/IE8)toType(document);//"htmldocument" (Chrome/FF/Safari) "document" (IE9) "object" (IE7/IE8)toType(document.createElement('a'));//"htmlanchorelement" (Chrome/FF/Safari/IE) "object" (IE7/IE8)toType(alert);//"function" (Chrome/FF/Safari/IE9) "object" (IE7/IE8)Модифицированный вариант функции:
function getTypeName(value) {
if (value === null) {
return "null";
}
var t = typeof value;
switch(t) {
case "function":
case "object":
if (value.constructor) {
if (value.constructor.name) {
return value.constructor.name;
} else {
// Internet Explorer
// Anonymous functions are stringified
// as follows: 'function () {}'
// => the regex below does not match
var match = value.constructor.toString().match(/^function (.+)\(.*$/);
if (match) {
return match[1];
}
}
}
// fallback, for nameless constructors etc.
return Object.prototype.toString.call(value).match(/^\[object (.+)\]$/)[1];
default:
return t;
}
}
Комментариев нет :
Отправить комментарий