Typeof en JavaScript es en realidad muy complejo. Puede usarse para hacer muchas cosas, pero también tiene muchos comportamientos extraños. Este artículo enumera sus múltiples usos y también señala los problemas y soluciones existentes.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof
> tipo de indefinido
'indefinido'
> tipo de nulo // error conocido
'objeto'
> tipo de verdadero
'booleano'
>tipo de 123
'número'
> tipo de "abc"
'cadena'
> tipo de función() {}
'función'
> tipo de {}
'objeto'
> tipo de []
'objeto'
> tipo de variable desconocida
'indefinido'
1. Compruebe si una variable existe y tiene un valor.
typeof devolverá "indefinido" en dos situaciones: cuando una variable no está declarada y cuando el valor de una variable no está definido.
> tipo de Variable no declarada === "indefinido" verdadero > var Variable declarada; > tipo de Variable declarada 'indefinido' > tipo de variable no definida 'indefinido'
Hay otras formas de detectar si un valor no está definido:
> valor var = indefinido > valor === indefinido verdadero;
Pero si este método se usa en una variable no declarada, se generará una excepción, porque solo typeof puede detectar variables no declaradas normalmente sin informar un error:
> Variable no declarada === Error de referencia no definido: la variable no declarada no está definida
Nota: Las variables no inicializadas, los parámetros formales sin parámetros pasados y las propiedades inexistentes no tendrán los problemas anteriores, porque siempre son accesibles y el valor siempre está indefinido:
> var Variable declarada; > Variable declarada === indefinido verdadero > (función (x) { return x === indefinido }()) verdadero > ({}).foo === indefinido verdadero
Nota del traductor: por lo tanto, si desea detectar la existencia de una variable global que no puede declararse, también puede usar if(window.maybeUndeclaredVariable){}
Problema: typeof es engorroso para realizar tal tarea.
Solución: este tipo de operación no es muy común, por lo que algunas personas sienten que no es necesario encontrar una solución mejor, pero tal vez alguien proponga un operador especial:
> definida Variable no declarada falsa > var Variable declarada > definida Variable declarada falsa;
O tal vez también se necesite un operador que detecte si una variable está declarada:
> variable no declarada declarada falsa > var variable declarada > variable declarada declarada verdadera;
Nota del traductor: en Perl, el operador definido arriba es equivalente a definido (), y el operador declarado arriba es equivalente a existe ().
2. Determine si un valor no es igual a indefinido o nulo.
Problema: si desea verificar si se ha definido un valor (el valor no es ni indefinido ni nulo), entonces se encuentra con una de las peculiaridades más famosas de typeof (considerada un error): typeof null devuelve "objeto":
> tipo de 'objeto' nulo
Nota del traductor: Esto solo se puede decir que es un error en la implementación original de JavaScript, y así es como ahora se estandariza el estándar V8 una vez revisado e implementado typeof null === "null", pero finalmente resultó inviable http: //wiki .ecmascript.org/doku.php?id=harmony:typeof_null
Solución: no use typeof para esta tarea, use una función como esta en su lugar:
función isDefined(x) { return x !== null && x !== indefinido }
Otra posibilidad es introducir un "operador de valor predeterminado", donde la siguiente expresión devuelva defaultValue si myValue no está definido:
miValor ?? valor predeterminado
La expresión anterior es equivalente a:
(miValor! == indefinido && miValor! == nulo)?
O:
miValor ??= Valor predeterminado
De hecho, es una simplificación de la siguiente afirmación:
miValor = miValor ??
Cuando accedes a una propiedad anidada, como una barra, es posible que necesites la ayuda de este operador:
obj.foo.bar
Si obj u obj.foo no están definidos, la expresión anterior generará una excepción. Un operador.?? permite que la expresión anterior devuelva el primer valor encontrado al atravesar las propiedades capa por capa. Propiedades que no están definidas o son nulas:
obj.??foo.??barra
La expresión anterior es equivalente a:
(obj === indefinido || obj === nulo) ? obj: (obj.foo === indefinido || obj.foo === nulo)?
3. Distinguir entre valores de objeto y valores primitivos.
La siguiente función prueba si x es un valor de objeto:
la función esObjeto(x) { return (tipo de x === "función" || (tipo de x === "objeto" && x! == nulo));
Problema: la detección anterior es complicada porque typeof considera funciones y objetos como tipos diferentes, y typeof null devuelve "objeto".
Solución: El siguiente método también se utiliza a menudo para detectar valores de objetos:
función esObjeto2(x) { return x === Objeto(x }
Advertencia: puede pensar que puede usar el objeto instancia de detección aquí, pero instancia de determina la relación de instancia utilizando el prototipo de un objeto, entonces, ¿qué pasa con los objetos sin prototipos?
> var obj = Object.create(nulo); > Object.getPrototypeOf(obj) nulo;
obj es de hecho un objeto, pero no es una instancia de ningún valor:
> tipo de obj 'objeto' > obj instancia de Objeto falso
En la práctica, es posible que rara vez te encuentres con un objeto de este tipo, pero existe y tiene sus usos.
Nota del traductor: Object.prototype es un objeto que existe de forma predeterminada y no tiene prototipo.
>Object.getPrototypeOf(Object.prototype)null>tipo de Object.prototype'object'>Object.prototype instancia de Objeto falso
4.¿Cuál es el tipo de valor primitivo?
typeof es la mejor manera de comprobar el tipo de un valor primitivo.
> tipo de "abc" 'cadena' > tipo de indefinido 'indefinido'
Problema: debes tener en cuenta el comportamiento extraño de typeof null.
> tipo de nulo // ¡Cuidado! 'objeto'
Solución: La siguiente función puede solucionar este problema (solo para este caso de uso).
function getPrimitiveTypeName(x) { var typeName = typeof x; switch(typeName) { case "undefinido": case "boolean": case "number": case "string": devuelve typeName; = null) { return "null"; } default: // Ninguno de los juicios anteriores aprobados arroja un nuevo TypeError("El parámetro no es un valor primitivo: "+x);
Una mejor solución: implementar una función getTypeName(), que además de devolver el tipo del valor original, también puede devolver el atributo interno [[Clase]] del valor del objeto. A continuación se explica cómo implementar esta función (Nota del traductor: jQuery $.type es una implementación de este tipo)
5. Si un determinado valor es una función
typeof se puede utilizar para detectar si un valor es una función > typeof function () {} 'function' > typeof Object.prototype.toString 'function'.
En principio, instancia de La función también puede detectar este requisito A primera vista, parece que el método de escritura es más elegante. Sin embargo, el navegador tiene una peculiaridad: cada marco y ventana tiene sus propias variables globales. El objeto se pasa a otro marco, instancia de no funcionará correctamente porque los dos marcos tienen constructores diferentes. Es por eso que existe un método Array.isArray() en ECMAScript 5. Sería bueno si hubiera un método entre marcos para verificar si un objeto es una instancia de un constructor determinado. El getTypeName( ) anterior es una solución alternativa disponible. , pero puede haber una solución más fundamental.
6.Descripción general
Las siguientes funciones mencionadas deberían ser las más urgentemente necesarias en JavaScript en la actualidad y pueden reemplazar algunas de las funciones funcionales de las responsabilidades actuales de typeof:
isDefined() (como Object.isDefined()): se puede utilizar como función o operador
esObjeto()
getTypeName()
Un mecanismo entre marcos para detectar si un objeto es una instancia de un constructor específico
Es posible que la necesidad de comprobar si una variable ha sido declarada no requiera su propio operador.