Zusammenfassung verschiedener Methoden zur JS-Datentyperkennung

Zusammenfassung verschiedener Methoden zur JS-Datentyperkennung

Hintergrund

Wie wir alle wissen, ist js eine dynamische, schwach typisierte Skriptsprache, die ein dynamisches Typsystem und prototypbasierte Vererbung verwendet.

Das Fehlen statischer Einschränkungen für Typen bedeutet, dass durch Datentypen verursachte Programmfehler während der Kompilierungsphase nicht rechtzeitig entdeckt werden können. Um robusten Code zu schreiben, müssen zur Laufzeit verschiedene Prüfungen und Kompatibilitäten durchgeführt werden. Daher ist die Fähigkeit, Datentypen geschickt und genau zu erkennen, zu einer der wichtigsten Grundlagen für die Beherrschung dieser Sprache geworden.

Welche Methoden gibt es zur Bestimmung von Datentypen?

Im Allgemeinen gibt es ungefähr die folgenden Typen: typeof, instanceof, Object.prototype.toString, Konstruktor, Duck-Typing und Erkennungsmethoden für bestimmte Typen Array.isArray(), Number.isNaN(). Obwohl es viele Methoden gibt, sind ihre Verwendungsszenarien unterschiedlich.

1. Verwenden Sie typeof, um den grundlegenden Datentyp zu bestimmen:

Die Rückgabewerte sind undefiniert, Zeichenfolge, Zahl, Boolescher Wert, Objekt, Funktion und Symbol.

Es ist ersichtlich, dass typeof als offiziell bereitgestellter Typerkennungsoperator sehr zuverlässig grundlegende Datentypen und Funktionen wie undefined, String, Boolean und Symbol erkennt. Der Hauptgrund für die schlechte Leistung ist

1) Es kann nicht zwischen bestimmten Objekttypen (Array, Date, regExp) unterschieden werden.
2) typeof null === 'Objekt' // ist wahr. . . .

Defekt 2) lässt sich vermeiden, indem bei der Typbestimmung der Objektreferenz ein weiterer Satz hinzugefügt wird: typeof x === 'object' && x !== null. Allerdings stellt die Unfähigkeit, zwischen den einzelnen Objekttypen zu unterscheiden, tatsächlich ein großes Problem dar.

2. Verwenden Sie instanceof, um den Objektdatentyp zu bestimmen

Mit diesem Operator wird festgestellt, ob der Prototyp eines Konstruktors in der Prototypenkette des Zielobjekts vorkommt.

Dies ist eine prädiktive Erkennungsmethode. Sie gibt den Datentyp nicht direkt als Zeichenfolge zurück wie typeof. Stattdessen müssen Sie den Konstruktor des Objekttyps vorhersagen und schließlich einen booleschen Wert zurückgeben.

Die Erkennungsregel ist eigentlich aus dem Namen ersichtlich, der bestimmt, ob die Instanz von einem bestimmten Konstruktor erstellt wird. Nachdem wir nun das Prinzip kennen, implementieren wir unsere eigene Instanz von.

Funktion myInstanceof(Ziel,Konstruktor){
  const baseType = ['Zeichenfolge', 'Zahl', 'Boolescher Wert', 'undefiniert', 'Symbol']
    wenn (Basistyp.includes(Typ von(Ziel))) { return false }
    //Die Prototypenkette ist eigentlich eine verknüpfte Liste, die aus Objekten besteht. Durchlaufen Sie diese verknüpfte Liste,
  let Prototyp = Object.getPrototypeOf(Ziel);
    während(Prototyp){
        //Sobald es ein passendes Objekt in der Kette gibt, geben Sie true zurück.
      wenn (Prototyp === Konstruktor.Prototyp) {
        returniere wahr
      }anders{
        Prototyp = Objekt.getPrototypeOf(Prototyp)
      }
    }
    return false
}
console.log(meineInstanzvon([],Array))

In js können wir im Großen und Ganzen davon ausgehen, dass alles von Objekten stammt, denn obwohl Instanzen durch Konstruktoren erstellt werden, ist der Konstruktor selbst nur eine emotionslose Produktionsmaschine. Die Seele und der Charakter (öffentliche Eigenschaften und Methoden) der Instanz werden alle vom Prototypobjekt geteilt, auf das die Prototypeigenschaft des Konstruktors zeigt, und Prototypobjekte sind alle reine Objekte, die vom Objektkonstruktor erstellt werden, was die folgenden Konsequenzen hat.

Bei Arrays wird beim Durchlaufen der Objekte in der Prototypkette Array.prototype Object.prototype angezeigt.

Darüber hinaus ist es unmöglich, die durch Literalwerte erstellten Basisdatentypen zu beurteilen. Zum Beispiel

Wie können die oben genannten Mängel ausgeglichen werden? Die Antwort besteht darin, in den oben genannten speziellen Szenarien anstelle von instanceof den folgenden Konstruktor zu verwenden.

3. Verwenden Sie das Konstruktorattribut

Lassen Sie uns zunächst eines klarstellen. Der Konstruktor ist eine Eigenschaft des Prototyps, und die Instanz erbt vom Prototyp, sodass auf diese Eigenschaft auch direkt in der Instanz zugegriffen werden kann.
Schauen wir uns zunächst die universelle Leistung des Konstruktors an

Unerwartet gute Leistung, mit Ausnahme von null und undefiniert kann der Basistyp (Wrappertyp) oder Objekttyp mit einem Konstruktorattribut genau beurteilt werden.

Es kann Array|Object genau unterscheiden, da es nicht wie instanceof die gesamte Prototypenkette durchläuft, sondern nur Urteile über die Instanz vornimmt. Es gibt jedoch auch einen schwerwiegenden Fehler. Dieses Attribut der Instanz kann zu leicht geändert werden. Nach der Änderung wird diese Methode bedeutungslos.

4. toString-Methode

Zunächst einmal verfügt der Objekttyp oder Basistyp eines Verpackungsobjekts von js über eine toString-Methode. Der von Object.prototype.toString() geerbte Aufruf gibt den String-Tag „[Objekttyp]“ des entsprechenden Typs zurück.

Diese Methode ist wie ein zufälliger Schlag, um den Meister zu töten, und es fühlt sich an wie eine unbeabsichtigte Weidenpflanzung, die zu einem Weidenwald führt. Seine ursprüngliche Funktion besteht nur darin, eine Zeichenfolge abzurufen, die das Objekt darstellt. Jetzt wird es bei der JS-Typerkennung verwendet und seine Leistung ist sehr gut. Es funktioniert sehr gut für Basistypen und Objekttypen. Wenn wir auf einen Nachteil hinweisen müssen, können wir nur sagen, dass die zurückgegebene Zeichenfolge etwas kompliziert und nicht sehr bequem zu verwenden ist. Lassen Sie es uns jetzt vereinfachen.

Schreiben Sie zuerst eine vereinfachte Version

Funktion istTyp(Typ,Wert){
    returniere Object.prototype.toString.call(Wert) === `[Objekt ${Typ}]`
}
Konsole.log(istTyp('Array',[]))
console.log(istTyp('Nummer',1))

Dies ist nicht sehr praktisch in der Anwendung. Typparameter wie „Array“ und „Number“ können leicht falsch geschrieben werden. Daher ist zu hoffen, dass die Methode Parameter voreinstellen und eine Funktionsfabrik erstellen kann, um Funktionen wie „isArray“ aufzurufen und zurückzugeben. In der IDE verfügen Funktionsnamen über bessere Codehinweise als Zeichenfolgen und sind weniger anfällig für Rechtschreibfehler.

Funktion istTyp(Typ){
    Rückgabefunktion (Wert) {
        returniere Object.prototype.toString.call(Wert) === `[Objekt ${Typ}]`
    }
}

const isArray = isType('Array')
const istNummer = istTyp('Nummer')
console.log(istArray([]),istNummer(1))

Hier wird die Idee von Funktionen höherer Ordnung verwendet, Parameter beibehalten + eine neue Funktion zurückgeben. Man kann sich vorstellen, dass bind in js dies nicht nur binden, sondern auch Parameter beibehalten + eine neue Funktion zurückgeben kann, was auch hier geeignet ist.

Funktion istTyp(Typ,Wert){
    returniere Object.prototype.toString.call(Wert) === `[Objekt ${Typ}]`
}

const isArray = isType.bind(null,'Array')
const isNumber = isType.bind(null,'Number')
console.log(istArray([]),istNummer(1))

Wenn wir einen Schritt weiter gehen, können wir die Idee des Parameter-Curryings nutzen, um

Funktion istTyp(Typ,Wert){
    returniere Object.prototype.toString.call(Wert) === `[Objekt ${Typ}]`
}
Funktion aktuell (fn,...args1) {
    sei len = fn.length;
    Rückgabefunktion (...args2) {
        const args = args1.concat(args2);
        wenn (args.length < len) {
            gibt aktuell zurück (fn, ... args)
        }anders{
            Rückgabewert fn(...args)
        }
    }
}
const isArray = aktuell(isType,'Array')
const istNummer = aktuell(istTyp,'Nummer')
console.log(istArray([]),istNummer(1))

Ergänzen Sie abschließend die unterstützten Typen und Sie sind fertig.

Konstantentypen = [
    'Null',
    'Undefiniert',
    'Zeichenfolge',
    'Nummer',
    'Boolesch',
    'Objekt',
    "Anordnung",
    'Datum',
    'Funktion',
    'Regulärer Ausdruck',
    'Symbol',
    'Mathe',
]
const checkTypeUtil = {}
Typen.fürJeden((Typ)=>{
    checkTypeUtil[`ist${Typ}`] = aktuell(istTyp,Typ)
})
exportieren {
 checkTypeUtil
}
Konsole.log(checkTypeUtil.isArray([]))

5. Verwenden Sie Array.isArray, um das Array zu bestimmen

Wie oben erwähnt, kann instanceof zum Erkennen von Arrays verwendet werden. In der von iframe erstellten Umgebung mit mehreren Fenstern müssen Array und Array.prototype jedoch in jedem Fenster unterschiedlich sein, da die globale Fensterumgebung isoliert werden muss. Daher ist iframeA.Array.prototype ≠ iframeB.Array.prototype, sodass iframeA.arr instanceof iframeB.Array false zurückgeben muss. Dies ist ein Ereignis mit geringer Wahrscheinlichkeit, aber im Szenario der Verwendung von iframe ist es auch sehr wahrscheinlich, dass Werte aneinander übergeben werden. Bei der Verwendung von Array.isArray, das von ES6 bereitgestellt wird, tritt dieses Problem nicht auf und das Array kann genau beurteilt werden.

So kannst du pollen

wenn (!Array.isArray) {
  Array.isArray = Funktion(x) {
    returniere Object.prototype.toString.call(x) === '[Objekt-Array]';
  };
}

6. Unterscheiden Sie zwischen ArrayLike und Array

Die Definition der Array-Klasse lautet:

  • Hat eine Längeneigenschaft und andere Eigenschaften (Indizes) sind nicht-negative Ganzzahlen (Indizes im Objekt werden als Zeichenfolgen behandelt)
  • Verfügt nicht über die Methoden, die Arrays haben
Funktion ist wie Array (x) {
    wenn(!(Typ von x === 'Objekt' && x !== null)){
        return false
    }
    Rückgabetyp von x.length === 'Zahl' und x.length >= 0 und !Array.isArray(x)
}

Array-ähnliche Objekte können mit Array.from Array.prototype.slice.call(val) in echte Arrays umgewandelt werden.

7. Bestimmen Sie, ob ein Objekt ein reines Objekt (oder ein gewöhnliches Objekt) ist

Definition eines reinen Objekts: bezieht sich speziell auf Objekte, die auf die folgenden drei Arten erstellt wurden

  • neues Objekt
  • Objektliteralerstellung {}
  • Objekt.erstellen(null)

Die jQuery- und Lodash-Quellcodes werden mit der folgenden Methode erkannt

const funcToString = Funktion.prototype.toString
const objectCtorString = funcToString.call(Object)

Funktion isPlainObject(Wert){
    // Verwenden Sie toString, um zuerst andere Datentypen auszuschließen if(!value || !Object.prototype.toString.call(value) === "[object Object]"){
        return false
    }
    const proto = Object.getPrototypeOf(Wert)
    if(proto === null){//Kompatibel mit Object.create(null) return true
    }
    const Ctor = Object.prototype.hasOwnProperty.call(proto,'Konstruktor') && proto.Konstruktor;
    wenn(Typ von Ctor !== 'Funktion'){
        return false
    }
    // Hier verwenden wir den String, um zu bestimmen, ob der Konstruktor ein Objekt ist, anstatt direkt instanceof zu verwenden, um das oben erwähnte Problem unterschiedlicher Objekte in mehreren Fensterumgebungen zu vermeiden if(funcToString.call(Ctor) === objectCtorString){
        returniere wahr
    }
    return false
}
Konsole.log(isPlainObject(Objekt.erstellen(null)))
console.log(isPlainObject(neues Objekt))
console.log(isPlainObject({a:1}))

8. Wie erkennt man NaN? Was ist der Unterschied zwischen Number.isNaN und isNaN?

Fazit: Number.isNaN prüft streng, ob der übergebene Wert direkt gleich NaN ist.

isNaN führt zuerst eine Number()-Konvertierung durch und ermittelt dann, ob es NaN ist.

9. Ententypisierung

Tatsächlich ist die obige Verwendung des Konstruktors zur Bestimmung des Datentyps die Verwendung dieser Methode. Um zu bestimmen, ob es sich bei einem Tier um eine Ente handelt, können wir eine grobe Einschätzung auf Grundlage einfacher empirischer Beurteilungen vornehmen, etwa ob es wie eine Ente aussieht und wie eine Ente quakt.

Um beispielsweise festzustellen, ob ein Objekt ein Promise ist, können Sie Folgendes tun:

Funktion istPromise(x){
    if (!(x Instanz von Promise)) {
        return false
    }
    Rückgabetyp von x.then === 'Funktion'
}

Zusammenfassen

Dies ist das Ende dieses Artikels zur JS-Datentyperkennung. Weitere relevante Inhalte zur JS-Datentyperkennung finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung der Datentypen in den JavaScript-Grundlagen
  • Vier Methoden zur Datentypbeurteilung in JS
  • Über den Unterschied zwischen js typeof und instanceof bei der Beurteilung von Datentypen und deren Entwicklung und Verwendung
  • Detaillierte Erklärung der grundlegenden Syntax und Datentypen von JavaScript
  • Dieser Artikel entführt Sie in die Welt der js-Datentypen und Datenstrukturen
  • Vier Methoden zur Verwendung von JS zur Bestimmung von Datentypen
  • Detaillierte Erklärung der sieben Datentypen in JavaScript

<<:  Ausführliche Erläuterung der Konzepte und Verwendung von MySQL-Transaktionen

>>:  Bringen Sie Ihnen bei, wie Sie Hive3.1.2 auf Tencent Cloud erstellen

Artikel empfehlen

Installationsschritte für die chinesische Eingabemethode von Ubuntu 20.04

Dieser Artikel installiert die Google-Eingabemeth...

Nutzerbedürfnisse führen zu marketingorientiertem Design

<br />Zu jedem unserer Themen bespricht das ...

SQL-Implementierung von LeetCode (182. Doppelte Postfächer)

[LeetCode] 182.Doppelte E-Mails Schreiben Sie ein...

Grundlegende Hinweise zu HTML und CSS (unbedingt für das Frontend lesen)

Als ich zum ersten Mal mit HTML in Berührung kam,...

MySQL-Techniken zum schnellen Datenvergleich

Im MySQL-Betrieb und bei der Wartung möchte ein F...

Wie implementiert MySQL ACID-Transaktionen?

Vorwort Kürzlich wurde ich in einem Interview gef...

Detailliertes Tutorial zur Installation des Quellcodes von CentOS6.9+Mysql5.7.18

Bei der Installation des Quellcodes von CentOS6.9...

Der Prozess der Bereitstellung eines Projekts auf einem anderen Host mit Jenkins

Umfeld Hostname IP-Adresse Aufschlag Jenkins 192....