Gibt es eine JavaScript Äquivalent von Java 's class.getName()
?
Antworten
Zu viele Anzeigen?Gibt es ein JavaScript-Äquivalent zu Javas
class.getName()
?
Nein .
ES2015 Aktualisierung : den Namen von class Foo {}
es Foo.name
. Der Name des thing
Klasse, unabhängig von thing
der Typ ist thing.constructor.name
. Eingebaute Konstruktoren in einer ES2015-Umgebung haben die richtige name
Eigenschaft; zum Beispiel (2).constructor.name
es "Number"
.
Aber hier sind verschiedene Hacks, die alle auf die eine oder andere Weise scheitern:
Hier ist ein Hack, der das tut, was Sie brauchen - seien Sie sich bewusst, dass er den Prototyp des Objekts verändert, etwas, das die Leute nicht gutheißen (normalerweise aus gutem Grund)
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
Jetzt haben alle Ihre Objekte die Funktion, getName()
die den Namen des Konstruktors als String zurückgibt. Ich habe dies getestet in FF3
y IE7
Ich kann nicht für andere Implementierungen sprechen.
Wenn Sie das nicht tun wollen, finden Sie hier eine Diskussion über die verschiedenen Arten der Typbestimmung in JavaScript...
Ich habe diese Liste kürzlich aktualisiert, um sie etwas ausführlicher zu gestalten, obwohl sie das kaum ist. Korrekturen sind willkommen...
を使用しています。 constructor
Eigentum...
Alle object
hat einen Wert für seine constructor
Eigenschaft, aber je nachdem, wie diese object
konstruiert wurde und was Sie mit diesem Wert tun wollen, kann er nützlich sein oder auch nicht.
Im Allgemeinen können Sie die constructor
Eigenschaft, um den Typ des Objekts wie folgt zu testen:
var myArray = [1,2,3];
(myArray.constructor == Array); // true
Das reicht also für die meisten Bedürfnisse aus. Davon abgesehen...
Vorbehalte
Wird nicht funktionieren ALLE in vielen Fällen
Dieses Muster ist zwar gebrochen, aber durchaus üblich:
function Thingy() {
}
Thingy.prototype = {
method1: function() {
},
method2: function() {
}
};
Objects
erstellt über new Thingy
haben eine constructor
Eigenschaft, die auf Object
, nicht Thingy
. Wir fallen also gleich zu Beginn: Sie können einfach nicht vertrauen constructor
in einer Codebasis, über die Sie keine Kontrolle haben.
Mehrfache Vererbung
Ein Beispiel, bei dem dies nicht so offensichtlich ist, ist die Verwendung von Mehrfachvererbung:
function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a
Die Dinge funktionieren jetzt nicht mehr so, wie man es vielleicht erwartet:
var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true
Sie könnten also unerwartete Ergebnisse erhalten, wenn die object
Ihre Prüfung hat eine andere object
gesetzt als seine prototype
. Es gibt Möglichkeiten, dies zu umgehen, die den Rahmen dieser Diskussion sprengen würden.
Es gibt weitere Verwendungszwecke für das constructor
Einige davon sind interessant, andere nicht so sehr; wir werden uns jetzt nicht mit diesen Verwendungen befassen, da sie für diese Diskussion nicht relevant sind.
Funktioniert nicht rahmenübergreifend und fensterübergreifend
使用方法 .constructor
für die Typprüfung bricht ab, wenn Sie den Typ von Objekten prüfen wollen, die von verschiedenen window
Objekte, z. B. eines iframe oder eines Popup-Fensters. Das liegt daran, dass es von jedem Kerntyp eine andere Version gibt constructor
in jedem "Fenster", d. h.
iframe.contentWindow.Array === Array // false
を使用しています。 instanceof
Betreiber...
El instanceof
Operator ist eine saubere Methode zur Prüfung object
Typs, hat aber auch seine eigenen potenziellen Probleme, genau wie der constructor
Eigentum.
var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true
Aber instanceof
funktioniert nicht für Literalwerte (weil Literale nicht Objects
)
3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false
Die Literale müssen in eine Hülle aus Object
damit instanceof
zur Arbeit, zum Beispiel
new Number(3) instanceof Number // true
El .constructor
Prüfung funktioniert gut für Literale, weil die .
Methodenaufruf die Literale implizit in ihren jeweiligen Objekttyp verpackt
3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true
Warum zwei Punkte für die 3? Weil Javascript den ersten Punkt als Dezimalpunkt interpretiert ;)
Funktioniert nicht rahmenübergreifend und fensterübergreifend
instanceof
funktioniert auch nicht unter verschiedenen Windows, und zwar aus demselben Grund wie die constructor
Eigentumsprüfung.
を使用しています。 name
Eigenschaft der constructor
Eigentum...
Funktioniert nicht ALLE in vielen Fällen
Wiederum siehe oben; es ist durchaus üblich, dass constructor
als völlig falsch und nutzlos erweisen.
Funktioniert NICHT in <IE9
使用方法 myObjectInstance.constructor.name
gibt Ihnen eine Zeichenkette mit dem Namen des constructor
Funktion verwendet, unterliegt aber den Vorbehalten bezüglich der constructor
Eigentum, die bereits erwähnt wurden.
Für IE9 und höher können Sie Pflaster zur Unterstützung :
if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
Object.defineProperty(Function.prototype, 'name', {
get: function() {
var funcNameRegex = /function\s+([^\s(]+)\s*\(/;
var results = (funcNameRegex).exec((this).toString());
return (results && results.length > 1) ? results[1] : "";
},
set: function(value) {}
});
}
Aktualisierte Version aus dem fraglichen Artikel. Dies wurde 3 Monate nach der Veröffentlichung des Artikels hinzugefügt. Dies ist die vom Autor des Artikels, Matthew Scharley, empfohlene Version, die zu verwenden ist. Diese Änderung wurde angeregt durch Kommentare, die auf mögliche Fallstricke hinweisen im vorherigen Code.
if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
Object.defineProperty(Function.prototype, 'name', {
get: function() {
var funcNameRegex = /function\s([^(]{1,})\(/;
var results = (funcNameRegex).exec((this).toString());
return (results && results.length > 1) ? results[1].trim() : "";
},
set: function(value) {}
});
}
Verwendung von Object.prototype.toString
Es stellt sich heraus, dass diese Stelle Details können Sie verwenden Object.prototype.toString
- die einfache und generische Implementierung von toString
- um den Typ für alle eingebauten Typen zu erhalten
Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]
Man könnte eine kurze Hilfsfunktion schreiben wie
function type(obj){
return Object.prototype.toString.call(obj).slice(8, -1);
}
um den Ballast zu entfernen und nur den Typnamen zu erhalten
type('abc') // String
Es wird jedoch zurückgegeben Object
für alle benutzerdefinierten Typen.
Vorbehalte für alle...
Bei all dem gibt es ein mögliches Problem, nämlich die Frage, wie das betreffende Objekt konstruiert wurde. Im Folgenden werden verschiedene Arten der Erstellung von Objekten und die Werte, die die verschiedenen Methoden der Typüberprüfung zurückgeben, beschrieben:
// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object); // true
(obj instanceof Foo); // true
(obj.constructor == Foo); // true
(obj.constructor.name == "Foo"); // true
// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object); // true
(obj instanceof Foo); // true
(obj.constructor == Foo); // false
(obj.constructor.name == "Foo"); // false
// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object); // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == ""); // true
// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object); // true
(obj instanceof Foo); // true
(obj.constructor == Foo); // true
(obj.constructor.name == ""); // true
// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object); // true
(obj.constructor == Object); // true
(obj.constructor.name == "Object"); // true
In diesen Beispielen sind zwar nicht alle Permutationen enthalten, aber hoffentlich genug, um Ihnen eine Vorstellung davon zu vermitteln, wie unübersichtlich die Dinge je nach Ihren Bedürfnissen werden könnten. Nehmen Sie nichts an. Wenn Sie nicht genau verstehen, was Sie wollen, kann es passieren, dass der Code an Stellen bricht, an denen Sie es nicht erwarten, weil Sie die Feinheiten nicht kennen.
HINWEIS:
Diskussion über die typeof
Operator mag als eklatantes Versäumnis erscheinen, aber er ist wirklich nicht hilfreich, um zu erkennen, ob ein object
ist ein bestimmter Typ, da er sehr einfach ist. Verstehen, wo typeof
nützlich ist, ist wichtig, aber ich habe nicht den Eindruck, dass es für diese Diskussion von großer Bedeutung ist. Meine Meinung kann sich jedoch ändern :)
Update
Um genau zu sein, denke ich, dass OP nach einer Funktion fragte, die den Konstruktornamen für ein bestimmtes Objekt abruft. In Bezug auf Javascript, object
hat keinen Typ, sondern ist ein Typ an und für sich . Verschiedene Objekte können jedoch unterschiedliche Konstrukteure .
Object.prototype.getConstructorName = function () {
var str = (this.prototype ? this.prototype.constructor : this.constructor).toString();
var cname = str.match(/function\s(\w*)/)[1];
var aliases = ["", "anonymous", "Anonymous"];
return aliases.indexOf(cname) > -1 ? "Function" : cname;
}
new Array().getConstructorName(); // returns "Array"
(function () {})().getConstructorName(); // returns "Function"
Anmerkung: das folgende Beispiel ist veraltet.
A Blogbeitrag verbunden durch Christian Sciberras enthält ein gutes Beispiel dafür, wie man es machen kann. Nämlich durch die Erweiterung des Prototyps Object:
if (!Object.prototype.getClassName) {
Object.prototype.getClassName = function () {
return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1];
}
}
var test = [1,2,3,4,5];
alert(test.getClassName()); // returns Array
Sie sollten Folgendes verwenden somevar.constructor.name
wie ein:
const getVariableType = a => a.constructor.name.toLowerCase();
const d = new Date();
const res1 = getVariableType(d); // 'date'
const num = 5;
const res2 = getVariableType(num); // 'number'
const fn = () => {};
const res3 = getVariableType(fn); // 'function'
console.log(res1); // 'date'
console.log(res2); // 'number'
console.log(res3); // 'function'
- See previous answers
- Weitere Antworten anzeigen