Gibt es eine JavaScript - Äquivalent von Java ‚s class.getName()
?
Gibt es eine JavaScript - Äquivalent von Java ‚s class.getName()
?
Antworten:
Gibt es ein JavaScript-Äquivalent zu Java
class.getName()
?
Nein .
ES2015 Update : Der Name class Foo {}
istFoo.name
. Der Name der thing
Klasse thing
lautet unabhängig vom Typ thing.constructor.name
. Eingebaute Konstruktoren in einer ES2015-Umgebung haben die richtige name
Eigenschaft. zum Beispiel (2).constructor.name
ist "Number"
.
Aber hier sind verschiedene Hacks, die alle auf die eine oder andere Weise herunterfallen:
Hier ist ein Hack, der das tut, was Sie brauchen - seien Sie sich bewusst, dass er den Prototyp des Objekts modifiziert, etwas, das die Leute missbilligen (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 Zeichenfolge zurückgibt. Ich habe dies in getestet FF3
und IE7
kann nicht für andere Implementierungen sprechen.
Wenn Sie dies nicht möchten, finden Sie hier eine Diskussion über die verschiedenen Möglichkeiten zur Bestimmung von Typen in JavaScript ...
Ich habe dies kürzlich aktualisiert, um es etwas ausführlicher zu gestalten, obwohl es kaum so ist. Korrekturen willkommen ...
constructor
Eigenschaft ...Jeder object
hat einen Wert für seine constructor
Eigenschaft, aber je nachdem, wie dieser erstellt object
wurde und was Sie mit diesem Wert tun möchten, kann er nützlich sein oder auch nicht.
Im Allgemeinen können Sie die constructor
Eigenschaft verwenden, um den Typ des Objekts wie folgt zu testen:
var myArray = [1,2,3];
(myArray.constructor == Array); // true
Das funktioniert also gut genug für die meisten Bedürfnisse. Das gesagt...
Wird nicht funktionieren AT ALL in vielen Fällen
Dieses Muster ist zwar gebrochen, aber weit verbreitet:
function Thingy() {
}
Thingy.prototype = {
method1: function() {
},
method2: function() {
}
};
Objects
Konstruiert über new Thingy
wird eine constructor
Eigenschaft haben, die zeigt Object
, nicht Thingy
. Wir fallen also gleich zu Beginn; Sie können einfach nicht constructor
auf eine Codebasis vertrauen , die Sie nicht kontrollieren.
Mehrfachvererbung
Ein Beispiel, bei dem dies nicht so offensichtlich ist, ist die Verwendung der Mehrfachvererbung:
function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a
Die Dinge funktionieren jetzt nicht so, wie Sie es vielleicht erwarten:
var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true
Daher erhalten Sie möglicherweise unerwartete Ergebnisse, wenn für object
Ihre Tests ein anderer object
Satz als der für Sie festgelegt wurde prototype
. Es gibt Möglichkeiten, dies außerhalb des Rahmens dieser Diskussion zu umgehen.
Es gibt andere Verwendungszwecke für das constructor
Eigentum, einige davon interessant, andere weniger; Im Moment werden wir uns nicht mit diesen Verwendungen befassen, da sie für diese Diskussion nicht relevant sind.
Funktioniert nicht über Rahmen und Fenster hinweg
Die Verwendung .constructor
für die Typprüfung wird unterbrochen, wenn Sie den Typ von Objekten überprüfen möchten, die von verschiedenen window
Objekten stammen, z. B. von einem Iframe oder einem Popup-Fenster. Dies liegt daran, dass es constructor
in jedem "Fenster" eine andere Version jedes Kerntyps gibt, d. H.
iframe.contentWindow.Array === Array // false
instanceof
Operators ...Der instanceof
Bediener ist ebenfalls eine saubere Methode zum Testen des object
Typs, hat jedoch genau wie die constructor
Eigenschaft seine eigenen potenziellen Probleme .
var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true
Funktioniert aber instanceof
nicht für wörtliche Werte (weil Literale dies nicht sind Objects
)
3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false
Die Literale müssen zum Beispiel in ein eingewickelt Object
werden, damit instanceof
sie funktionieren
new Number(3) instanceof Number // true
Die .constructor
Prüfung funktioniert gut für Literale, da der .
Methodenaufruf die Literale implizit in ihren jeweiligen Objekttyp einschließt
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;)
instanceof
funktioniert auch nicht über verschiedene Fenster hinweg, aus dem gleichen Grund wie die constructor
Eigenschaftsprüfung.
name
Eigenschaft der constructor
Eigenschaft ...Wieder siehe oben; Es ist durchaus üblich constructor
, völlig falsch und nutzlos zu sein.
Mit using erhalten myObjectInstance.constructor.name
Sie eine Zeichenfolge, die den Namen der verwendeten constructor
Funktion enthält, jedoch den constructor
zuvor erwähnten Einschränkungen bezüglich der Eigenschaft unterliegt .
Für IE9 und höher können Sie Affen-Patches zur Unterstützung verwenden :
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 des betreffenden Artikels. Dies wurde 3 Monate nach Veröffentlichung des Artikels hinzugefügt. Dies ist die empfohlene Version, die vom Autor des Artikels, Matthew Scharley, verwendet wird. Diese Änderung wurde durch Kommentare inspiriert, die auf mögliche Fallstricke im vorherigen Code hinweisen .
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) {}
});
}
Es stellt sich heraus, dass Sie, wie in diesem Beitrag beschrieben , Object.prototype.toString
die einfache und generische Implementierung von verwenden können toString
, um den Typ für alle integrierten Typen abzurufen
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 wie schreiben
function type(obj){
return Object.prototype.toString.call(obj).slice(8, -1);
}
um die Kruft zu entfernen und nur den Typnamen zu erhalten
type('abc') // String
Es wird jedoch Object
für alle benutzerdefinierten Typen zurückgegeben.
All dies unterliegt einem potenziellen Problem, und das ist die Frage, wie das betreffende Objekt konstruiert wurde. Hier sind verschiedene Möglichkeiten zum Erstellen von Objekten und die Werte, die die verschiedenen Methoden der Typprüfung zurückgeben:
// 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
Obwohl in diesen Beispielen nicht alle Permutationen vorhanden sind, gibt es hoffentlich genug, um Ihnen eine Vorstellung davon zu geben, wie chaotisch die Dinge je nach Ihren Anforderungen werden können. Nehmen Sie nichts an. Wenn Sie nicht genau verstehen, wonach Sie suchen, kann es sein, dass Sie Code brechen, wo Sie dies nicht erwarten, weil Sie die Feinheiten nicht verstehen.
Die Diskussion des typeof
Operators mag als eklatante Auslassung erscheinen, ist jedoch nicht hilfreich, um festzustellen, ob object
es sich um einen bestimmten Typ handelt, da dies sehr einfach ist. Es typeof
ist wichtig zu verstehen, wo es nützlich ist, aber ich glaube derzeit nicht, dass es für diese Diskussion schrecklich relevant ist. Mein Geist ist jedoch offen für Veränderungen. :) :)
constructor
Methode des Objekts (entweder mit .toString()
oder .name
) untersuchen, nicht funktionieren, wenn Ihr Javascript mit einem Tool wie uglify oder der Rails-Asset-Pipeline minimiert wurde. Durch die Minimierung wird der Konstruktor umbenannt, sodass Sie falsche Klassennamen wie erhalten n
. Wenn Sie sich in diesem Szenario befinden, möchten Sie möglicherweise nur manuell eine className
Eigenschaft für Ihre Objekte definieren und diese stattdessen verwenden.
Die Antwort von Jason Bunting gab mir genug Anhaltspunkte, um herauszufinden, was ich brauchte:
<<Object instance>>.constructor.name
So zum Beispiel im folgenden Code:
function MyObject() {}
var myInstance = new MyObject();
myInstance.constructor.name
würde zurückkehren "MyObject"
.
function getType(o) { return o && o.constructor && o.constructor.name }
Ein kleiner Trick, den ich benutze:
function Square(){
this.className = "Square";
this.corners = 4;
}
var MySquare = new Square();
console.log(MySquare.className); // "Square"
class Square
, lautet der Name Square.name
/ MySquare.constructor.name
statt Square.prototype.name
; Durch Aktivieren name
der Konstruktorfunktion wird der Prototyp oder eine Instanz nicht verschmutzt, sondern kann von beiden aus aufgerufen werden.
Um genau zu sein, hat OP nach einer Funktion gefragt, die den Konstruktornamen für ein bestimmtes Objekt abruft. In Bezug auf Javascript hat object
es keinen Typ, sondern ist ein Typ von und für sich . Unterschiedliche Objekte können jedoch unterschiedliche Konstruktoren haben .
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"
Hinweis: Das folgende Beispiel ist veraltet.
Ein von Christian Sciberras verlinkter Blog-Beitrag enthält ein gutes Beispiel dafür. Durch Erweitern des Objektprototyps:
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
test.getClassName()
vs getClassName.apply(test)
.
Verwenden von Object.prototype.toString
Wie in diesem Beitrag beschrieben, können Sie Object.prototype.toString - die einfache und generische Implementierung von toString - verwenden, um den Typ für alle integrierten Typen abzurufen
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 wie schreiben
function type(obj){
return Object.prototype.toString.call(obj]).match(/\s\w+/)[0].trim()
}
return [object String] as String
return [object Number] as Number
return [object Object] as Object
return [object Undefined] as Undefined
return [object Function] as Function
.slice()
:Object.prototype.toString.call(obj).slice( 8, -1 );
Hier ist eine Lösung, die ich gefunden habe und die die Mängel von instanceof behebt. Es kann die Typen eines Objekts anhand von Fenstern und Rahmen überprüfen und hat keine Probleme mit primitiven Typen.
function getType(o) {
return Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/)[1];
}
function isInstance(obj, type) {
var ret = false,
isTypeAString = getType(type) == "String",
functionConstructor, i, l, typeArray, context;
if (!isTypeAString && getType(type) != "Function") {
throw new TypeError("type argument must be a string or function");
}
if (obj !== undefined && obj !== null && obj.constructor) {
//get the Function constructor
functionConstructor = obj.constructor;
while (functionConstructor != functionConstructor.constructor) {
functionConstructor = functionConstructor.constructor;
}
//get the object's window
context = functionConstructor == Function ? self : functionConstructor("return window")();
//get the constructor for the type
if (isTypeAString) {
//type is a string so we'll build the context (window.Array or window.some.Type)
for (typeArray = type.split("."), i = 0, l = typeArray.length; i < l && context; i++) {
context = context[typeArray[i]];
}
} else {
//type is a function so execute the function passing in the object's window
//the return should be a constructor
context = type(context);
}
//check if the object is an instance of the constructor
if (context) {
ret = obj instanceof context;
if (!ret && (type == "Number" || type == "String" || type == "Boolean")) {
ret = obj.constructor == context
}
}
}
return ret;
}
isInstance erfordert zwei Parameter: ein Objekt und einen Typ. Der eigentliche Trick bei der Funktionsweise besteht darin, zu überprüfen, ob das Objekt aus demselben Fenster stammt und ob das Objektfenster nicht abgerufen wird.
Beispiele:
isInstance([], "Array"); //true
isInstance("some string", "String"); //true
isInstance(new Object(), "Object"); //true
function Animal() {}
function Dog() {}
Dog.prototype = new Animal();
isInstance(new Dog(), "Dog"); //true
isInstance(new Dog(), "Animal"); //true
isInstance(new Dog(), "Object"); //true
isInstance(new Animal(), "Dog"); //false
Das Typargument kann auch eine Rückruffunktion sein, die einen Konstruktor zurückgibt. Die Rückruffunktion erhält einen Parameter, der das Fenster des bereitgestellten Objekts ist.
Beispiele:
//"Arguments" type check
var args = (function() {
return arguments;
}());
isInstance(args, function(w) {
return w.Function("return arguments.constructor")();
}); //true
//"NodeList" type check
var nl = document.getElementsByTagName("*");
isInstance(nl, function(w) {
return w.document.getElementsByTagName("bs").constructor;
}); //true
Beachten Sie, dass IE <9 den Konstruktor nicht für alle Objekte bereitstellt, sodass der obige Test für NodeList false zurückgibt und auch eine isInstance (Warnung, "Funktion") false zurückgibt.
Ich suchte tatsächlich nach einer ähnlichen Sache und stieß auf diese Frage. So bekomme ich Typen: jsfiddle
var TypeOf = function ( thing ) {
var typeOfThing = typeof thing;
if ( 'object' === typeOfThing ) {
typeOfThing = Object.prototype.toString.call( thing );
if ( '[object Object]' === typeOfThing ) {
if ( thing.constructor.name ) {
return thing.constructor.name;
}
else if ( '[' === thing.constructor.toString().charAt(0) ) {
typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
}
else {
typeOfThing = thing.constructor.toString().match( /function\s*(\w+)/ );
if ( typeOfThing ) {
return typeOfThing[1];
}
else {
return 'Function';
}
}
}
else {
typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
}
}
return typeOfThing.charAt(0).toUpperCase() + typeOfThing.slice(1);
}
Sie sollten somevar.constructor.name
wie folgt verwenden :
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'
Die Funktion kind () von Agave.JS gibt Folgendes zurück:
Es funktioniert mit allen JS-Objekten und Grundelementen, unabhängig davon, wie sie erstellt wurden , und bietet keine Überraschungen. Beispiele:
kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'
kind(NaN) === 'NaN'
kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'
kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'
kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'
kind({a:1}) === 'Object'
kind(new Object()) === 'Object'
kind(new Date()) === 'Date'
kind(function(){}) === 'Function'
kind(new Function("console.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'
kind(undefined) === 'undefined'
kind(null) === 'null'
Sie können den instanceof
Operator verwenden, um festzustellen, ob ein Objekt eine Instanz eines anderen ist. Da jedoch keine Klassen vorhanden sind, können Sie keinen Klassennamen abrufen.
instanceof
prüft aber nur, ob ein Objekt von einem anderen Objekt erbt. ZB []
erbt ein einfaches von Array, aber Array erbt auch von Object. Da die meisten Objekte mehrere Vererbungsebenen haben, ist es besser , den nächstgelegenen Prototyp zu finden . Siehe meine Antwort für wie.
Hier ist eine Implementierung basierend auf der akzeptierten Antwort :
/**
* Returns the name of an object's type.
*
* If the input is undefined, returns "Undefined".
* If the input is null, returns "Null".
* If the input is a boolean, returns "Boolean".
* If the input is a number, returns "Number".
* If the input is a string, returns "String".
* If the input is a named function or a class constructor, returns "Function".
* If the input is an anonymous function, returns "AnonymousFunction".
* If the input is an arrow function, returns "ArrowFunction".
* If the input is a class instance, returns "Object".
*
* @param {Object} object an object
* @return {String} the name of the object's class
* @see <a href="https://stackoverflow.com/a/332429/14731">https://stackoverflow.com/a/332429/14731</a>
* @see getFunctionName
* @see getObjectClass
*/
function getTypeName(object)
{
const objectToString = Object.prototype.toString.call(object).slice(8, -1);
if (objectToString === "Function")
{
const instanceToString = object.toString();
if (instanceToString.indexOf(" => ") != -1)
return "ArrowFunction";
const getFunctionName = /^function ([^(]+)\(/;
const match = instanceToString.match(getFunctionName);
if (match === null)
return "AnonymousFunction";
return "Function";
}
// Built-in types (e.g. String) or class instances
return objectToString;
};
/**
* Returns the name of a function.
*
* If the input is an anonymous function, returns "".
* If the input is an arrow function, returns "=>".
*
* @param {Function} fn a function
* @return {String} the name of the function
* @throws {TypeError} if {@code fn} is not a function
* @see getTypeName
*/
function getFunctionName(fn)
{
try
{
const instanceToString = fn.toString();
if (instanceToString.indexOf(" => ") != -1)
return "=>";
const getFunctionName = /^function ([^(]+)\(/;
const match = instanceToString.match(getFunctionName);
if (match === null)
{
const objectToString = Object.prototype.toString.call(fn).slice(8, -1);
if (objectToString === "Function")
return "";
throw TypeError("object must be a Function.\n" +
"Actual: " + getTypeName(fn));
}
return match[1];
}
catch (e)
{
throw TypeError("object must be a Function.\n" +
"Actual: " + getTypeName(fn));
}
};
/**
* @param {Object} object an object
* @return {String} the name of the object's class
* @throws {TypeError} if {@code object} is not an Object
* @see getTypeName
*/
function getObjectClass(object)
{
const getFunctionName = /^function ([^(]+)\(/;
const result = object.constructor.toString().match(getFunctionName)[1];
if (result === "Function")
{
throw TypeError("object must be an Object.\n" +
"Actual: " + getTypeName(object));
}
return result;
};
function UserFunction()
{
}
function UserClass()
{
}
let anonymousFunction = function()
{
};
let arrowFunction = i => i + 1;
console.log("getTypeName(undefined): " + getTypeName(undefined));
console.log("getTypeName(null): " + getTypeName(null));
console.log("getTypeName(true): " + getTypeName(true));
console.log("getTypeName(5): " + getTypeName(5));
console.log("getTypeName(\"text\"): " + getTypeName("text"));
console.log("getTypeName(userFunction): " + getTypeName(UserFunction));
console.log("getFunctionName(userFunction): " + getFunctionName(UserFunction));
console.log("getTypeName(anonymousFunction): " + getTypeName(anonymousFunction));
console.log("getFunctionName(anonymousFunction): " + getFunctionName(anonymousFunction));
console.log("getTypeName(arrowFunction): " + getTypeName(arrowFunction));
console.log("getFunctionName(arrowFunction): " + getFunctionName(arrowFunction));
//console.log("getFunctionName(userClass): " + getFunctionName(new UserClass()));
console.log("getTypeName(userClass): " + getTypeName(new UserClass()));
console.log("getObjectClass(userClass): " + getObjectClass(new UserClass()));
//console.log("getObjectClass(userFunction): " + getObjectClass(UserFunction));
//console.log("getObjectClass(userFunction): " + getObjectClass(anonymousFunction));
//console.log("getObjectClass(arrowFunction): " + getObjectClass(arrowFunction));
console.log("getTypeName(nativeObject): " + getTypeName(navigator.mediaDevices.getUserMedia));
console.log("getFunctionName(nativeObject): " + getFunctionName(navigator.mediaDevices.getUserMedia));
Wir verwenden die Konstruktoreigenschaft nur, wenn wir keine andere Wahl haben.
Mit dem Operator "instanceof" können Sie bestimmen, ob ein Objekt eine Instanz einer bestimmten Klasse ist oder nicht. Wenn Sie den Namen des Objekttyps nicht kennen, können Sie dessen Konstruktoreigenschaft verwenden. Die Konstruktoreigenschaft von Objekten ist ein Verweis auf die Funktion, mit der sie initialisiert werden. Beispiel:
function Circle (x,y,radius) {
this._x = x;
this._y = y;
this._radius = raduius;
}
var c1 = new Circle(10,20,5);
Jetzt ist c1.constructor eine Referenz auf die Circle()
Funktion. Sie können den typeof
Operator auch verwenden, der typeof
Operator zeigt jedoch nur begrenzte Informationen an. Eine Lösung besteht darin, die toString()
Methode des globalen Objektobjekts zu verwenden. Wenn Sie beispielsweise ein Objekt haben, z. B. myObject, können Sie die toString()
Methode des globalen Objekts verwenden, um den Typ der Klasse von myObject zu bestimmen. Benutze das:
Object.prototype.toString.apply(myObject);
Sagen Sie, Sie haben var obj;
Wenn Sie nur den Namen des Typs von obj wie "Object", "Array" oder "String" möchten, können Sie Folgendes verwenden:
Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');
Der nächstgelegene Wert ist typeof
, gibt jedoch nur "Objekt" für einen benutzerdefinierten Typ zurück. Für diese siehe Jason Bunting .
Bearbeiten, Jason hat seinen Beitrag aus irgendeinem Grund gelöscht, verwenden Sie also einfach die constructor
Eigenschaft von Object .
Wenn jemand nach einer Lösung gesucht hat, die mit jQuery funktioniert, finden Sie hier den angepassten Wiki-Code (das Original bricht jQuery).
Object.defineProperty(Object.prototype, "getClassName", {
value: function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}
});
getName
und fällt um.
Lodash hat viele isMethods. Wenn Sie also Lodash verwenden, kann ein Mixin wie dieses nützlich sein:
// Mixin for identifying a Javascript Object
_.mixin({
'identify' : function(object) {
var output;
var isMethods = ['isArguments', 'isArray', 'isArguments', 'isBoolean', 'isDate', 'isArguments',
'isElement', 'isError', 'isFunction', 'isNaN', 'isNull', 'isNumber',
'isPlainObject', 'isRegExp', 'isString', 'isTypedArray', 'isUndefined', 'isEmpty', 'isObject']
this.each(isMethods, function (method) {
if (this[method](object)) {
output = method;
return false;
}
}.bind(this));
return output;
}
});
Es fügt eine Methode namens "Identifizieren" zu lodash hinzu, die wie folgt funktioniert:
console.log(_.identify('hello friend')); // isString
Ok, Leute, ich habe über einige Jahre langsam eine Catch-All-Methode dafür entwickelt, lol! Der Trick ist:
Ein Beispiel (oder um zu sehen, wie ich mit dem Problem umgegangen bin) finden Sie im folgenden Code auf github: https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js und suchen Sie nach:
classOf =
,
classOfIs =
Und oder
defineSubClass =
(ohne die Backticks ( `)).
Wie Sie sehen, sind einige Mechanismen vorhanden, um zu erzwingen classOf
, dass ich immer den Namen des Klassen- / Konstruktortyps bekomme, unabhängig davon, ob es sich um ein Grundelement, eine benutzerdefinierte Klasse, einen Wert handelt, der mit einem nativen Konstruktor erstellt wurde, Null, NaN usw. Für jeden einzelnen Javascript-Wert erhalte ich seinen eindeutigen Typnamen von der classOf
Funktion. Außerdem kann ich tatsächliche Konstruktoren übergeben sjl.classOfIs
, um den Typ eines Werts zu überprüfen, und zusätzlich den Typnamen übergeben! Also zum Beispiel:
`` `// Bitte vergib lange Namespaces! Ich hatte keine Ahnung von den Auswirkungen, bis ich sie für eine Weile benutzt habe (sie saugen haha)
var SomeCustomClass = sjl.package.stdlib.Extendable.extend({
constructor: function SomeCustomClass () {},
// ...
}),
HelloIterator = sjl.ns.stdlib.Iterator.extend(
function HelloIterator () {},
{ /* ... methods here ... */ },
{ /* ... static props/methods here ... */ }
),
helloIt = new HelloIterator();
sjl.classOfIs(new SomeCustomClass(), SomeCustomClass) === true; // `true`
sjl.classOfIs(helloIt, HelloIterator) === true; // `true`
var someString = 'helloworld';
sjl.classOfIs(someString, String) === true; // `true`
sjl.classOfIs(99, Number) === true; // true
sjl.classOf(NaN) === 'NaN'; // true
sjl.classOf(new Map()) === 'Map';
sjl.classOf(new Set()) === 'Set';
sjl.classOfIs([1, 2, 4], Array) === true; // `true`
// etc..
// Also optionally the type you want to check against could be the type's name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!
`` `
Wenn Sie mehr darüber erfahren möchten, wie ich das oben erwähnte Setup verwende, schauen Sie sich das Repo an: https://github.com/elycruz/sjljs
Auch Bücher mit Inhalten zum Thema: - "JavaScript Patterns" von Stoyan Stefanov. - "Javascript - Der endgültige Leitfaden." von David Flanagan. - und viele andere .. (Suche im Web).
Sie können auch die Funktionen, über die ich hier spreche, schnell testen: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (auch der Pfad 0.5.18 in der URL enthält die Quellen von github dort abzüglich der node_modules und so).
Viel Spaß beim Codieren!
function getType(entity){
var x = Object.prototype.toString.call(entity)
return x.split(" ")[1].split(']')[0].toLowerCase()
}
function checkType(entity, type){
return getType(entity) === type
}