Introdución
Unha das características de idioma de JavaScript máis controvertida é a súa letra suave ou dinámica que xa falamos de cando en vez. Isto significa que, a diferenza doutras linguas clásicas como C ou Java, cando declaramos variables, non necesitamos especificar o tipo de datos que conteñen. O que é máis, a mesma variable, pode posuír varios tipos diferentes en diferentes momentos de execución: pode comezar a ser todo un todo, converterse nunha matriz e posterior, por exemplo, acaba sendo un obxecto.
Esta flexibilidade ten Vantaxes moi interesantes para o desenvolvemento de aplicacións complexas xa que non hai limitacións a priori sobre o que unha variable pode almacenar. Non obstante, para aqueles que veñen doutras linguas de punta duras, un dos problemas deste concepto é que é moi difícil identificar o tipo de datos específico que unha variable ten nun determinado momento de execución.
Identificar O tipo
Efectivamente, JavaScript non posúe un medio universitario para identificar o tipo de datos que contén unha variable nun momento determinado. Nativamente, temos dúas instrucións que nos poden dar un valor aproximado pero que, por desgraza, non son definitivas: tipo e instancia.
O tipo de operador
Typeof é un operador Unar, que o que significa que só acepta (e opera) nun único argumento; Neste caso, unha variable:
typorof 2; // numpypeof 'hello mundo' // stringtypeof // obxecto
Este operador non é unha función; Non obstante, as parénteses pódense usar para agrupar os termos que se deben avaliar:
typeof (2); // nubtypeof ('hello mundo'); // stringtypeof ('foo', 4); // Número
Nota: Argument Groupings en JavaScript Determine o valor final dun elemento a través do uso de operadores internos. Estes operadores indican a orde en que se avalían os termos, como a coma, o que fai que esta avaliación de esquerda ata o dereito de devolver o valor do segundo operando. Para obter máis información sobre este aspecto de idioma, recoméndase o elemento do operador de commona de JavaScript.
A seguinte táboa mostra a correspondencia de obxectos de JavaScript e o valor obtido con TYPEF:
tipo | resultado |
---|---|
indefinido | “Undefined” |
null | “obxecto” |
booleano | “boolean” |
número | “número” |
cadea | “cadea” |
obxecto host (dentro do JS Ambiente) | depende da implementación |
función | |
Obxecto XML E4X | “XML” |
XMLLIST E4X | “XML” |
Calquera outro obxecto | “obxecto |
Como podemos nós Ver Non hai ningunha referencia na táboa antes de elementos como arrays, datas, expresións regulares, etc. Isto significa que para Typeof, eses elementos son un obxecto máis. Ademais, vemos algúns resultados que poden parecer confusos como nulos nos que temos como un tipo de “obxecto”:
Typeof Nan; // Nubtypeof Infinity; // nubtypeof (1/0); // nubertypeof (tipopef); // cadea
Parece que non podemos confiar neste operador demasiado para determinar o tipo de datos que avaliamos, polo que pode ser interesante buscar outro máis seguro ou completo solución.
obxecto.prototipo.string
A función Tostring, devolve unha cadea que representa o obxecto indicado como argumento:
Object.prototype.fring (); //
Vexamos o resultado: “”: Segundo a especificación de ECMASCRIPT5, o obxecto.Prototipo.String retorna como resultado a concatenación da cadea “obxecto” máis valor interno do obxecto o que se pasa (o que chamamos clase – clase) …
]
Todos os obxectos de JavaScript teñen un propietario interno coñecido como] (a notación con trazado dobre é o mesmo que se usa na especificación ES5). Segundo es5,] é unha cadea cun valor único (non editable) que identifica cada obxecto. Por iso, un obxecto invocado co constructor e que non foi modificado, devolve como valor desta propiedade o tipo de obxecto preciso ao que pertence:
var o = novo obxecto (); ou.tosting (); //
Con todo, vemos que este operador tamén é fráxil cando o aplicamos en obxectos comúns:
.fring (); // "foo, bar, 1" "Hello World" .Tostring (); // "Hello World" /A-Z/.Testring (); // "/ a-z /"
Isto é así porque os obxectos personalizados sobrescriben o método obxectoTotOtype.String co seu propio. Unha forma de resolver isto é invocar este método directamente do obxecto do obxecto e usar a función de chamada para inxectar o argumento desexado:
obxecto.prothotype.tring.call (); // obxecto.prototipo.toscall ("Hello World"); // obxecto.prototipo.tring.call (/ a-z /); //
Deste xeito, evitamos sobreescribir calquera cousa e o resultado obtido é esperado: temos o tipo de datos correcto.
creando unha función a Determine o tipo de datos
extraídos directamente do artigo de Angus Croll, podemos usar a seguinte función para obter o tipo de datos correcto dunha variable ou obxecto:
vartype = función (obj) {return ({}). Tostring.call (obj) .match (/ s (+) /) . Tolowercase ()}
imos examinalo en partes:
- ({}). Tostring é unha abreviatura (un atallo) do obxecto .Prototipo. Xusta desde que, en calquera outro obxecto, o método de Tostring refírese á definición dada por obxecto.Prototipo como vimos arriba.
- Chamada que usamos aquí para que o método anterior estea feito no argumento que indicamos, neste caso, outro obxecto.
- Match: Utilizamos unha expresión regular para extraer o tipo de datos sen o Caden A inicial ‘obxecto’ e os parénteses. Usamos unha expresión regular en lugar dunha porción ou outro método debido ao mellor rendemento que ofrece sobre o resto.
- Tolowercase: Pasamos por minúsculas para diferenciar o tipo de que sería a referencia á instancia de Un obxecto e que, xeralmente, é maiúscula.
Vexamos como a función compórtase:
Totype ({a: 4}); // "obxecto" Totype (); // "Array" (función () {console.log (Totype (argumentos))); // argumentostotype (new referenceError); // "Erro" Totype (data nova); // "Data" Totype (/ a-z /); // "regexp" Totype (matemáticas); // "Math" Totype (JSON); // "json" Totype (novo número (4)); // "Número" Totype (nova cadea ("ABC"); // "cadea" Totype (New Boolean (TRUE)); // "booleano"
e imos comparalo co que recibiríamos con Typeof:
typeof {a: 4}; // tipo "obxecto"; // "obxecto" (función () {console.log (tipo de argumentos)}) (); // objetypeof new referenceError; // "Obxecto" Tipoteca nova data; // "obxecto" Tipof / a-z /; // "Obxecto" Tipo de matemática; // "Obxecto" Tipof JSON; // "obxecto" tipo novo (4); // "obxecto" Tipof nova cadea ("ABC"); // "Obxecto" Tipof New Boolean (TRUE); // "Obxecto"
A diferenza na maioría dos casos é importante: a partir da imprecisión de TYPEOF seguimos a obter tipos específicos.
comparación con instancia
O operador de instancia comproba a cadea prototípica do primeiro operando que busca a presenza da propiedade prototípica do segundo, que se espera que se corresponda cun constructor:
Nova data InstanceOf Data; // Array de instancia verdadeira; // True
O problema deste operador é que algúns obxectos en JavaScript non teñen un constructor asociado para que non sexan avaliados correctamente por instancia:
instancia math math // typeError
Hai tamén o problema deses ambientes con múltiples cadros onde a presenza de varios contextos globais (un para cada cadro) impida asegurar que un obxecto dado sexa unha instancia dun determinado constructor:
var iframe = document.createlement ('iframe'); document.body.appendchild (iframe); var iframeRray = window.frames.Array; var array = novo iframeray (); Array de instancia de matriz; // FalaRray instancef iframeray; // TRUE;
Limitacións
A función de totype non se pode evitar a partir de erros contra tipos de datos descoñecidos:
objet.totipo (FFF); // referencError
Especificamente, é a chamada a TOTYPE que lanza o erro, non a función en si. O único xeito de evitar que isto estaría usando a comparación implícita que nos permite o sistema de circuíto curto de JavaScript:
window.fff & &.Totype (FFF);
Se se cumpre a primeira condición, continúase o seguinte; Se non, o circuíto é cortado e é evitado o erro.
Conclusión
En JavaCript, non podemos determinar con precisión o tipo de datos dunha variable usando os métodos nativos que proporciona a lingua en si mesmo. Normalmente, cando necesitamos identificar tipos, normalmente recorremos a técnicas aproximadas, como a escritura de pato. Non obstante, nas aplicacións onde a integridade é crítica, esta técnica non permite que o rigor sexa necesario.
TIPOOF e instancia non ofrecen un control rigoroso, fiable e inactivo sobre os tipos que poderiamos necesitar durante un desenvolvemento. Para tratar de resolver esta falta, usamos algunhas das peculiaridades da linguaxe como o valor], para lograr un resultado moito máis preciso.
Este artigo é unha tradución expandida do orixinal de Angus Croll: Fixando o Operador de Typeof JavaScript.