Identificazione dinamica del tipo
Identificazione dinamica del tipo (RTTI) consente di determinare il tipo di un oggetto in fase di esecuzione. Risulta essere utile per una serie di motivi. In particolare, facendo riferimento alla classe base, è possibile determinare con precisione il tipo di oggetto accessibile da questo riferimento. L'identificazione dinamica del tipo consente inoltre di verificare in anticipo l'esito positivo del casting del tipo, prevenendo un'eccezione dovuta a un casting del tipo errato. Inoltre, l'identificazione dinamica del tipo è una componente importante della riflessione.
Per supportare l'identificazione dinamica del tipo, C# ne fornisce tre parole chiave a: is, as e typeof. Ognuna di queste parole chiave viene discussa ulteriormente a sua volta.
è operatore
Il tipo specifico di un oggetto può essere determinato utilizzando l'operatore is. Di seguito la sua forma generale:
l'espressione è tipo
dove espressione denota una singola espressione che descrive l'oggetto il cui tipo viene testato. Se l'espressione è di tipo compatibile o dello stesso tipo del tipo testato, il risultato di questa operazione è vero, altrimenti è falso. Pertanto, il risultato sarà vero se l'espressione è del tipo testato in una forma o nell'altra. Nell'operatore is, entrambi i tipi sono definiti come compatibili se sono dello stesso tipo o se viene fornita la conversione dei riferimenti, il boxing o l'unboxing.
Di seguito è riportato un esempio di utilizzo dell'operatore is:
Utilizzando il sistema; namespace ConsoleApplication1 ( class Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); if (a is Add) Console.WriteLine("Variabile a è di tipo Add"); if (s è Sum) Console.WriteLine("Il tipo di variabile s è ereditato dalla classe Add"); Console.ReadLine(); ) ) )
come operatore
A volte una conversione di tipo deve essere eseguita in fase di esecuzione, ma non generata se la conversione fallisce, il che è perfettamente possibile con un cast di tipo. L'operatore as serve a questo scopo e ha la seguente forma generale:
espressione come tipo
dove espressione denota una singola espressione convertibile nel tipo specificato.
Se il risultato di tale conversione ha esito positivo, viene restituito un riferimento al tipo, in caso contrario, un riferimento null. L'operatore as può essere utilizzato solo per conversione di riferimento, identità, boxing, unboxing. In alcuni casi, l'operatore as può essere una comoda alternativa all'operatore is. A titolo di esempio, si consideri il seguente programma:
Utilizzando il sistema; namespace ConsoleApplication1 ( class Add ( ) class Sum: Add ( ) class Program ( static void Main() ( Add a = new Add(); Sum s = new Sum(); // Esegue cast a = s come Add; if ( a != null) Console.WriteLine("Conversione riuscita"); else Console.WriteLine("Errore durante la conversione"); Console.ReadLine(); ) ) )
Il risultato dell'esecuzione di questo programma sarà una conversione riuscita.
a = (b > 0) && (c + 1 != d); indicatore = !(stato = 0);
Tabella 14.5. Operatori logici
Descrizione dell'operatore
! NOT (inversione logica)
&& AND (moltiplicazione booleana)
|| OR (addizione logica)
Tabella 14.6. Risultati dell'esecuzione degli operatori AND e OR
Operando 1 |
Operando 2 |
||
Tabella 14.7. Risultati dell'esecuzione dell'istruzione NOT
ottenere il tipo di operatore
Ottieni operatore di tipo typeof restituisce una stringa che descrive il tipo di dati dell'operando. L'operando di cui si vuole trovare il tipo è posto dopo questo operatore e racchiuso tra parentesi:
s = typeof("str");
Come risultato di questa espressione, la variabile s conterrà la stringa "string" , che denota il tipo di stringa.
Tutti i valori che possono essere restituiti tipo di operatore sono elencati in Tabella. 14.8.
Tabella 14.8. Valori restituiti dall'operatore typeof |
||
Tipo di dati |
Stringa di ritorno |
|
Corda |
||
Numerico |
||
Tabella 14.8 (fine) |
|||
Tipo di dati |
Stringa di ritorno |
||
Logico |
|||
Compatibilità e conversione del tipo di dati
È giunto il momento di considerare due questioni più importanti: la compatibilità dei tipi di dati e la conversione da un tipo all'altro.
Cosa succede quando si sommano due numeri insieme? Esatto, un altro valore numerico. Cosa succede se aggiungi un numero e una stringa? È difficile da dire... Qui JavaScript incontra il problema dell'incompatibilità dei tipi di dati e cerca di rendere compatibili questi tipi convertendo uno di essi in un altro. Prima prova a convertire la stringa in un numero e, se ci riesce, esegue l'addizione. In caso di esito negativo, il numero verrà convertito in una stringa e le due stringhe risultanti verranno concatenate. Ad esempio, lo script Web nel Listato 14-6 convertirà il valore della variabile b quando aggiunto alla variabile a in un tipo numerico; quindi la variabile c conterrà il valore 23.
Listato 14.6
var a, b, c, d, e, f; un = 11;
b = "12"; c = la + b;
d="Javascript"; e = 2;
Ma poiché il valore della variabile d non può essere convertito in un numero, il valore di e verrà convertito in una stringa e il risultato - il valore di f - diventerà uguale a
I valori booleani vengono convertiti in valori numerici o stringa, a seconda dei casi. True verrà convertito nel numero 1 o nella stringa "1" e false in 0 o "0" . Al contrario, il numero 1 verrà convertito in true e il numero 0 in false . Inoltre, false verrà convertito
siamo nulli e indefiniti.
Parte III. Comportamento della pagina web. Script web |
|
Si può vedere che JavaScript fa fatica a eseguire correttamente anche le espressioni scritte in modo errato. A volte funziona, ma il più delle volte le cose non funzionano come previsto e alla fine lo script Web viene interrotto perché viene rilevato un errore in un punto completamente diverso dello script, nell'affermazione assolutamente corretta. Pertanto, è meglio evitare tali incidenti.
Precedenza dell'operatore
L'ultimo problema di cui ci occuperemo qui è la precedenza degli operatori. Come ricordiamo, la precedenza influisce sull'ordine in cui vengono eseguiti gli operatori in un'espressione.
Sia la seguente espressione:
In questo caso al valore della variabile b verrà prima aggiunto il valore di c, quindi alla somma verrà sottratto 10. Gli operatori di questa espressione hanno la stessa precedenza e quindi vengono eseguiti rigorosamente da sinistra verso destra.
Consideriamo ora questa espressione:
Qui, prima, il valore c verrà moltiplicato per 10 e solo allora il valore b verrà aggiunto al prodotto risultante. L'operatore di moltiplicazione ha una precedenza maggiore rispetto all'operatore di addizione, pertanto l'ordine "rigorosamente da sinistra a destra" verrà violato.
Gli operatori di assegnazione hanno la precedenza più bassa. Ecco perché l'espressione stessa viene valutata per prima, quindi il suo risultato viene assegnato a una variabile.
A In generale, il principio di base dell'esecuzione di tutti gli operatori è il seguente: prima vengono eseguiti gli operatori con una priorità più alta e solo allora gli operatori con una priorità inferiore. Gli operatori con la stessa precedenza vengono eseguiti nell'ordine in cui appaiono (da sinistra a destra).
A scheda. 14.9 elenca tutti gli operatori che abbiamo studiato in ordine decrescente di precedenza.
Tabella 14.9. Precedenza degli operatori (in ordine decrescente) |
||
Operatori |
Descrizione |
|
++ -- - ~ ! tipo di |
Incremento, decremento, cambio di segno, NOT logico, inferenza di tipo |
|
Moltiplicazione, divisione, resto |
||
Addizione e concatenazione di stringhe, sottrazione |
||
Operatori di confronto |
||
AND logico |
||
Capitolo 14. Introduzione alla programmazione web. linguaggio javascript |
|||
Tabella 14.9 (fine) |
|||
Operatori |
Descrizione |
||
OR logico |
|||
Operatore condizionale (vedi sotto) |
|||
= <оператор>= |
Compito, semplice e complesso |
||
ATTENZIONE!
Ricorda questa tabella. L'errato ordine di esecuzione delle istruzioni può causare errori difficili da rilevare, in cui un'espressione apparentemente assolutamente corretta dà un risultato errato.
Ma cosa succede se abbiamo bisogno di rompere il normale ordine di esecuzione delle istruzioni? Usiamo le parentesi. In questa notazione, le istruzioni tra parentesi vengono eseguite per prime:
a = (b + c) * 10;
Qui verranno prima aggiunti i valori delle variabili b e c, quindi la somma risultante verrà moltiplicata per 10.
Anche gli operatori racchiusi tra parentesi sono soggetti a precedenza. Pertanto, vengono spesso utilizzate più parentesi nidificate:
a = ((b + c) * 10 - d) / 2 + 9;
Qui le istruzioni verranno eseguite nel seguente ordine:
1. Aggiungere b e c.
2. Moltiplica l'importo risultante per 10.
3. Sottrarre d dal prodotto.
4. Dividi la differenza per 2.
5. Addizione di 9 al quoziente.
Se rimuovi le parentesi:
a = b + c * 10 - d / 2 + 9;
quindi l'ordine di esecuzione degli operatori sarà il seguente:
1. Moltiplica c e 10.
2. Dividi d per 2.
3. Sommando b e moltiplicando c e 10.
4. Sottrazione dalla somma risultante del quoziente dalla divisione d a 2.
5. Aggiungendo 9 alla differenza risultante.
Si scopre un risultato completamente diverso, giusto?
javascript o JS(a breve) non è un linguaggio facile e gli sviluppatori alle prime armi non lo impareranno subito. All'inizio imparano le basi e tutto sembra colorato e bello. Andando un po' più a fondo, ci sono Array JavaScript, oggetti, richiami e tutto ciò che spesso lascia a bocca aperta.
In JavaScript, è importante controllare correttamente il tipo di una variabile. Diciamo che vuoi sapere se una variabile è un array o un oggetto? Come controllarlo correttamente? In questo caso particolare, ci sono trucchi durante la verifica ed è di questo che parlerà questo post. Iniziamo subito.
Verifica del tipo di una variabile
Ad esempio, è necessario verificare se una variabile è un oggetto, un array, una stringa o un numero. Puoi usare typeof per questo, ma non ti dirà sempre la verità, e ti mostrerò perché nell'esempio qui sotto.
Ho scritto questo esempio per illustrare perché typeof non è sempre la scelta giusta.
Var _comparison = ( string: "string", int: 99, float: 13.555, object: (hello: "hello"), array: new Array(1, 2, 3) ); // Restituisce un array con le chiavi dell'oggetto var _objKeys = Object.keys(_comparison); for(var i = 0; i<= _objKeys.length - 1; i++) { // выведем в консоль тип каждой переменной console.log(typeof _comparson[_objKeys[i]]); }
Risultato dell'esecuzione del codice:
String numero oggetto oggetto
Destra? - Ovviamente no. Ci sono due problemi. Ciascuno di essi sarà descritto in dettaglio e verrà proposta una soluzione.
Primo problema: numero float, output come numero
Comparison.float non è un numero e deve essere un float anziché un numero. Per risolvere questo problema, puoi creare una funzione con un segno di spunta come nel codice seguente.
Var_floatNumber = 9.22; var_notFloatNumber = 9; console.log(isFloat(_floatNumber)); console.log(isFloat(_notFloatNumber)); console.log(isFloat("")); funzione isFloat(n)( return Numero(n) === n && n % 1 !== 0; )
La funzione isFloat() controlla tutti i valori per i numeri in virgola mobile. Per prima cosa controlla se la variabile è uguale n number (Number(n) === n) e se sì, viene effettuato un altro controllo per la divisione con resto e se c'è un resto, viene restituito un valore booleano ( VERO o falso) risultato (n % 1 !== 0).
Nell'esempio sopra, restituisce VERO, falso e falso. Il primo significato è galleggiante digitare, il secondo no - questo è un numero normale e l'ultimo è solo una stringa vuota che non si adatta alle regole.
Secondo problema: l'array è stato definito come un oggetto
Nel primissimo esempio, l'array viene visualizzato come un oggetto, il che non è molto buono, perché a volte è necessario utilizzare questo tipo e nient'altro.
Esistono diversi modi per testare una variabile per un tipo di matrice.
La prima opzione (buona opzione). Controlla se i dati appartengono a un array usando instanceof().
Var data = new Array("ciao", "mondo"); var isArr = data instanceof Array;
La seconda opzione (buona opzione). Il metodo Array.isArray() restituisce un valore booleano che dipenderà dal fatto che la variabile sia o meno un array ().
Var data = new Array("ciao", "mondo"); var isArr = Array.isArray(dati);
La terza opzione (la migliore, ma lunga). Per comodità, puoi rendere questo metodo una funzione. Usando Object creiamo . Se il risultato di Object.prototype.toString.call(data) non è uguale, la variabile non è un array ().
Var data = new Array("ciao", "mondo"); var isArr = Object.prototype.toString.call(data) == ""; console.log(isArr);
L'ultimo risultato come funzione di convenienza:
Funzione isArray(data) ( return Object.prototype.toString.call(data) == "" )
Ora puoi chiamare le funzioni isArray() e impostare un array o qualcosa del genere come argomento e vedere il risultato.
Epilogo
Il record si è rivelato piuttosto grande di quanto originariamente previsto. Ma sono contento perché è abbastanza conciso e chiaro da descrivere le difficoltà di convalidare le variabili in JavaScript e come aggirarle.
In caso di domande, si prega di pubblicarle sotto questo post. Sarò felice di aiutarti.
Operatore tipo di restituisce una stringa che indica il tipo di operando.
Sintassi
L'operando segue l'operatore typeof:
tipo di operando
Opzioni
operandoè un'espressione che rappresenta l'oggetto o la primitiva il cui tipo deve essere restituito.
Descrizione
La tabella seguente elenca i possibili valori restituiti di typeof . Ulteriori informazioni su tipi e primitive sono disponibili nella pagina.
Esempi
// Numeri typeof 37 === "numero"; typeof 3.14 === "numero"; typeof(42) === "numero"; typeof Math.LN2 === "numero"; typeof Infinity === "numero"; typeof NaN === "numero"; // anche se è "Not-A-Number" typeof Number(1) === "number"; // non usare mai questa notazione! // Stringhe typeof "" === "stringa"; typeof "bla" === "stringa"; typeof "1" === "stringa"; // nota che il numero all'interno della stringa è ancora di tipo string typeof (typeof 1) === "string"; // typeof restituirà sempre una stringa in questo caso typeof String("abc") === "string"; // non usare mai questa notazione! // Booleans typeof true === "boolean"; typeof false === "booleano"; typeof Boolean(true) === "boolean"; // non usare mai questa notazione! // Symbols typeof Symbol() === "simbolo" typeof Symbol("foo") === "simbolo" typeof Symbol.iterator === "simbolo" // Undefined typeof undefined === "undefined"; typeof DeclarationButUndefinedVariable === "undefined"; typeof undeclaredVariable === "undefined"; // Oggetti typeof(a: 1) === "oggetto"; // usa Array.isArray o Object.prototype.toString.call // per distinguere tra oggetti regolari e array typeof === "object"; typeof new Date() === "oggetto"; // Qualunque cosa sotto porta a errori e problemi. Non usare! typeof new Boolean(true) === "oggetto"; typeof new Number(1) === "oggetto"; typeof new String("abc") === "oggetto"; // Funzioni typeof function() () === "funzione"; typeof class C() === "funzione"; typeof Math.sin === "funzione";nullo
// Questo è stato definito sin dalla nascita di JavaScript typeof null === "object";Nella prima implementazione di JavaScript, i valori erano rappresentati da un tipo di tag e una coppia di valori. Il tipo di tag per gli oggetti era 0. null era rappresentato come un puntatore null (0x00 sulla maggior parte delle piattaforme). Pertanto, il tipo del tag per null era null, quindi il valore restituito di typeof è fasullo. ()
È stata proposta una correzione in ECMAScript (tramite disabilita) ma è stata respinta. Ciò risulterebbe in typeof null === "null" .
Utilizzo dell'operatore new
// Tutte le funzioni di costruzione create con "new" saranno di tipo "object" var str = new String("String"); var num = nuovo Numero(100); typeofstr; // Restituisce "oggetto" typeof num; // Restituisce "oggetto" // Ma c'è un'eccezione per il costruttore di funzioni var func = new Function(); tipo di funzione; // Restituisce "funzione"Espressioni regolari
Le espressioni regolari richiamate erano un'aggiunta non standard in alcuni browser.
Tipo di /s/ === "funzione"; // Chrome 1-12 Non compatibile con ECMAScript 5.1 typeof /s/ === "object"; // Firefox 5+ Conforme a ECMAScript 5.1
Bug relativi a zone morte temporanee
Prima di ECMAScript 2015, l'operatore typeof era garantito per restituire una stringa per qualsiasi operando con cui veniva chiamato. Ciò è cambiato con l'aggiunta di dichiarazioni let e const con ambito di blocco non di sollevamento. Ora, se le variabili vengono dichiarate con let e const e typeof viene richiamato su di esse nel blocco di dichiarazione delle variabili, ma prima della dichiarazione, viene generato un ReferenceError. Il comportamento è diverso dalle variabili non dichiarate, per le quali typeof restituirà "undefined". Le variabili con ambito di blocco si trovano in una "zona morta temporanea", che dura dall'inizio del blocco fino al momento in cui le variabili vengono dichiarate. In questa zona, un tentativo di accedere alle variabili genera un'eccezione.
Typeof undeclaredVariable === "undefined"; typeof newLetVariable; let newLetVariable; // ReferenceError typeof newConstVariable; const newConstVariable = "ciao"; // RiferimentoErrore
Eccezioni
In tutti i browser attuali esiste un oggetto host document.all non standard, che è di tipo Undefined.
Tipo di documento.all === "non definito";
Sebbene la specifica consenta nomi di tipi personalizzati per oggetti esotici non standard, questi nomi devono essere diversi da quelli predefiniti. La situazione in cui document.all è di tipo undefined dovrebbe essere considerata una violazione eccezionale delle regole.
Specifiche
Specifica | Stato | Commenti |
---|---|---|
ECMAScript ultima bozza (ECMA-262) |
Brutta copia | |
ECMAScript 2015 (6a edizione, ECMA-262) Definizione di "The typeof Operator" in questa specifica. |
Standard | |
ECMAScript 5.1 (ECMA-262) Definizione di "The typeof Operator" in questa specifica. |
Standard | |
ECMAScript 3a edizione (ECMA-262) Definizione di "The typeof Operator" in questa specifica. |
Standard | |
ECMAScript 1a edizione (ECMA-262) Definizione di "The typeof Operator" in questa specifica. |
Standard | Definizione iniziale. Implementato in JavaScript 1.1 |
Compatibilità browser
Aggiorna i dati di compatibilità su GitHub
Computer | Mobile | server | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Cromo | bordo | Firefox | Internet Explorer | musica lirica | safari | visualizzazione Web Android | Chrome per Android | Firefox per Android | Opera per Android | Safari su iOS | Samsung Internet | Node.js | |
tipo di | Cromo Supporto totale 1 | bordo Supporto totale 12 | Firefox Supporto totale 1 | CIOÈ Supporto totale 3 | musica lirica Supporto totale sì | safari Supporto totale sì | visualizzazione web android Supporto totale 1 | Chrome Android Supporto totale 18 | FirefoxAndroid Supporto totale 4 | OperaAndroid Supporto totale sì | Safari iOS Supporto totale sì | Samsung Internet Android Supporto totale 1.0 | nodejs Supporto totale sì |
Leggenda
Supporto totale Supporto totaleNote specifiche per IE
In IE 6, 7 e 8, molti oggetti host sono oggetti, non funzioni. Per esempio.