如何在JavaScript中获取对象types的名称?

有没有Java的class.getName()的JavaScript等价物?

有没有Java的class.getName()的JavaScript等价物?

没有

ES2015更新class Foo {}的名称是Foo.name 。 无论thing的types如何, thing类的名字都是thing.constructor.name 。 ES2015环境中的内build构造函数具有正确的name属性; 例如(2).constructor.name"Number"


但是,这里有各种各样的黑客以各种方式倒下:

这里有一个黑客会做你所需要的 – 要知道,它修改了对象的原型,人们皱眉(通常是出于很好的理由)

 Object.prototype.getName = function() { var funcNameRegex = /function (.{1,})\(/; var results = (funcNameRegex).exec((this).constructor.toString()); return (results && results.length > 1) ? results[1] : ""; }; 

现在,所有的对象都会有函数getName() ,它将以string的forms返回构造函数的名字。 我已经在FF3IE7testing过了,我不能说其他的实现。

如果你不想这样做,下面是关于在JavaScript中确定types的各种方法的讨论…


我最近更新了这个更详尽一点,虽然它几乎没有。 更正欢迎…

使用constructor属性…

每个object都有其constructor属性的值,但取决于该object构造方式以及要使用该值执行的操作,可能有用也可能无用。

一般来说,您可以使用constructor属性来testing对象的types,如下所示:

 var myArray = [1,2,3]; (myArray.constructor == Array); // true 

所以,对于大多数需求来说,这样做足够好。 那说…

注意事项

在许多情况下都不能工作

这种模式虽然被打破,但却是相当普遍的:

 function Thingy() { } Thingy.prototype = { method1: function() { }, method2: function() { } }; 

通过new Thingy构造的Objects将具有指向Objectconstructor属性,而不是Thingy 。 所以我们一开始就落伍了。 你不能信任你不能控制的代码库中的constructor

多重inheritance

一个不太明显的例子是使用多重inheritance:

 function a() { this.foo = 1;} function b() { this.bar = 2; } b.prototype = new a(); // b inherits from a 

事情现在不能​​像你所期望的那样工作:

 var f = new b(); // instantiate a new object with the b constructor (f.constructor == b); // false (f.constructor == a); // true 

所以,如果你的testingobject有一个不同的object集作为它的prototype ,你可能会得到意想不到的结果。 这个讨论的范围之外有办法。

还有其他用途的constructor属性,其中有些是有趣的,其他不是很多; 现在我们不会深入研究这些用途,因为它与这个讨论无关。

不会跨越框架和跨窗口工作

当你想检查来自不同window对象的对象的types时,使用.constructor进行types检查将会中断,比如iframe或popup窗口。 这是因为每个`window'中的每个核心typesconstructor都有不同的版本,

 iframe.contentWindow.Array === Array // false 

使用instanceof操作符…

instanceof运算符也是testingobjecttypes的一种干净的方式,但是它有自己的潜在问题,就像constructor属性一样。

 var myArray = [1,2,3]; (myArray instanceof Array); // true (myArray instanceof Object); // true 

但是instanceof不能用于文字值(因为文字不是Objects

 3 instanceof Number // false 'abc' instanceof String // false true instanceof Boolean // false 

例如,文字需要包装在一个Object中,以便instanceof工作

 new Number(3) instanceof Number // true 

.constructor检查工作正常的文字,因为. 方法调用隐式地将文字包装在它们各自的对象types中

 3..constructor === Number // true 'abc'.constructor === String // true true.constructor === Boolean // true 

为什么两个点为3? 因为Javascript将第一个点解释为小数点;)

不会跨越框架和跨窗口工作

instanceof也不会在不同的窗口中工作,出于与constructor属性检查相同的原因。


使用constructor属性的name属性…

在许多情况下都不起作用

再次,见上面; constructor完全错误和无用是很常见的。

在<IE9中不起作用

使用myObjectInstance.constructor.name将为您提供一个string,其中包含所使用的constructor函数的名称,但受限于前面提到的有关constructor属性的警告。

对于IE9及以上版本,您可以使用猴子补丁 :

 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) {} }); } 

相关文章的更新版本 。 这是在文章发表3个月后添加的,这是本文作者Matthew Scharley推荐的版本。 这个变化受到了评论的启发, 指出了前面的代码中潜在的缺陷 。

 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) {} }); } 

使用Object.prototype.toString

事实certificate,作为这篇文章的细节 ,您可以使用Object.prototype.toStringtoString的低级别和通用实现)来获取所有内置types的types

 Object.prototype.toString.call('abc') // [object String] Object.prototype.toString.call(/abc/) // [object RegExp] Object.prototype.toString.call([1,2,3]) // [object Array] 

人们可以写一个简短的帮助function,如

 function type(obj){ return Object.prototype.toString.call(obj).slice(8, -1); } 

删除cruft和得到只是types的名称

 type('abc') // String 

但是,它将为所有用户定义的types返回Object


所有的注意事项…

所有这些都有一个潜在的问题,那就是这个问题是如何构build的。 以下是构build对象的各种方法以及types检查的不同方法将返回的值:

 // 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 

虽然并不是所有的排列都出现在这个例子中,但是希望能给你一个关于如何根据你的需要得到混乱的东西的想法。 不要假设任何事情,如果你不能完全理解你以后的事情,你最终可能会因为缺乏对细节的不满而不期望的代码破解。

注意:

对操作符types的讨论似乎是一个明显的漏掉,但是在帮助识别一个object是否是给定types方面是没有用的,因为它非常简单。 了解typeof的用处很重要,但是我目前并不觉得这与这个讨论非常相关。 尽pipe我的想法可以改变。 🙂

杰森·邦廷的回答给了我足够的线索,find我所需要的:

 <<Object instance>>.constructor.name 

所以,例如,在下面这段代码中:

 function MyObject() {} var myInstance = new MyObject(); 

myInstance.constructor.name将返回"MyObject"

我使用一个小技巧:

 function Square(){ this.className = "Square"; this.corners = 4; } var MySquare = new Square(); console.log(MySquare.className); // "Square" 

更新

确切地说,我想OP要求一个函数来检索特定对象的构造函数名称。 在Javascript方面, object没有一个types,但本身就是一种types。 但是,不同的对象可以有不同的构造函数

 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" 

注意:以下示例已被弃用。

Christian Sciberras连接的博客文章包含了一个很好的例子。 也就是说,通过扩展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 

这是我提出的一个解决scheme,它解决了instanceof的缺点。 它可以从跨窗口和跨框架检查对象的types,并且不存在原始types的问题。

 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需要两个参数:一个对象和一个types。 它如何工作的真正诀窍是它检查对象是否来自同一个窗口,如果没有获取对象的窗口。

例子:

 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 

type参数也可以是一个返回构造函数的callback函数。 callback函数将接收一个参数,它是提供的对象的窗口。

例子:

 //"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 

需要注意的一点是,IE <9不提供所有对象的构造函数,所以上面的NodeListtesting将返回false,并且isInstance(alert,“Function”)将返回false。

您可以使用instanceof运算符来查看对象是否是另一个对象的实例,但由于没有类,因此无法获取类名称。

使用Object.prototype.toString

事实certificate,作为这篇文章的细节,您可以使用Object.prototype.toString(toString的低级别和通用实现)来获取所有内置types的types

 Object.prototype.toString.call('abc') // [object String] Object.prototype.toString.call(/abc/) // [object RegExp] Object.prototype.toString.call([1,2,3]) // [object Array] 

人们可以写一个简短的帮助function,如

 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 

Agave.JS的kind()函数将返回:

  • inheritance树中最接近的原型
  • 对于总是原始types,如“null”和“undefined”,原始名称。

它适用于所有JS对象和原语, 而不pipe它们是如何创build的 ,并且没有任何意外。 例子:

数字

 kind(37) === 'Number' kind(3.14) === 'Number' kind(Math.LN2) === 'Number' kind(Infinity) === 'Number' kind(Number(1)) === 'Number' kind(new Number(1)) === 'Number' 

为NaN

 kind(NaN) === 'NaN' 

string

 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' 

date

 kind(new Date()) === 'Date' 

function

 kind(function(){}) === 'Function' kind(new Function("console.log(arguments)")) === 'Function' kind(Math.sin) === 'Function' 

未定义

 kind(undefined) === 'undefined' 

空值

 kind(null) === 'null' 

可以的时候使用constructor.name ,当我不能的时候使用regex函数。

 Function.prototype.getName = function(){ if (typeof this.name != 'undefined') return this.name; else return /function (.+)\(/.exec(this.toString())[1]; }; 

我其实是在寻找类似的东西,并且遇到了这个问题。 这里是我如何获得types: 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); } 

您可以使用“instanceof”运算符来确定对象是否是某个类的实例。 如果您不知道对象types的名称,则可以使用其构造函数属性。 对象的构造函数属性是对用于初始化它们的函数的引用。 例:

 function Circle (x,y,radius) { this._x = x; this._y = y; this._radius = raduius; } var c1 = new Circle(10,20,5); 

现在c1.constructor是对Circle()函数的引用。 您可以使用typeof运算符,但typeof运算符显示有限的信息。 一个解决scheme是使用Object全局对象的toString()方法。 例如,如果有一个对象,比如说myObject,则可以使用全局对象的toString()方法来确定myObject类的types。 用这个:

 Object.prototype.toString.apply(myObject); 

你可以得到最接近的是typeof ,但它只返回任何types的自定义types的“对象”。 对于这些,请参阅杰森·邦廷 。

编辑,贾森删除他的职位出于某种原因,所以只需使用对象的constructor属性。

这是一个基于接受的答案的实现 :

 /** * 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 (eg 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)); 

如果有人正在寻找一个与jQuery合作的解决scheme,这里是调整后的wiki代码(原始的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] : ""; } }); 

Lodash有很多isMethods,所以如果你使用Lodash,也许这样的mixin可能是有用的:

  // 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; } }); 

它增加了一个叫做“识别”的方法,其工作原理如下:

 console.log(_.identify('hello friend')); // isString 

Plunker: http ://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN

好吧,我一直在慢慢build立一个所有的方法这几年哈哈! 诀窍是:

  1. 有一个创build类的机制。
  2. 有一个机制来检查所有用户创build的类,由原生构造函数创build/生成的基元和值。
  3. 有一个机制来将用户创build的类扩展为新的类,以便上述function渗透到代码/应用程序/库/等等中。

举一个例子(或者看看我是如何处理这个问题的),请看github上的以下代码: https : //github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js并search:

classOf =classOfIs =和/或defineSubClass = (没有反引号(`))。

正如你所看到的,我有一些机制强制classOf总是给我类/构造函数的types名称,无论它是基元,用户定义的类,使用本地构造函数创build的值,Null,NaN等等。 。对于每个单独的javascript值,我将从classOf函数中获取它的唯一types名称。 另外,我可以将实际的构造函数传入sjl.classOfIs中,除了可以传入types名称之外,还可以检查值的types。 举个例子:

“//请原谅长的命名空间! 我不知道这些影响,直到使用它们一段时间(他们吸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`! 

“`

如果你有兴趣阅读更多关于如何使用上面提到的安装程序,请查看repo: https : //github.com/elycruz/sjljs

还有关于这个主题的内容的书籍: – 斯托扬·斯特凡诺夫的“JavaScript模式”。 – “Javascript – 权威指南” 由大卫弗拉纳根。 – 和其他许多..(searchnetworking)。

您也可以快速testing我在这里讨论的function: – http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (同时在url中的0.5.18path有来自github在那里减去node_modules等)。

快乐编码!

说你有var obj;

如果你只是想要obj的types的名称,如“对象”,“数组”或“string”,你可以使用这个:

 Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');