获取对象类型的名称

时间:2008-12-01 22:06:16

标签: javascript

是否有Java的等效Java class.getName()

21 个答案:

答案 0 :(得分:1481)

答案 1 :(得分:112)

Jason Bunting的回答给了我足够的线索来找到我需要的东西:

<<Object instance>>.constructor.name

因此,例如,在下面的代码中:

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

myInstance.constructor.name会返回"MyObject"

答案 2 :(得分:25)

我使用的一个小技巧:

function Square(){
    this.className = "Square";
    this.corners = 4;
}

var MySquare = new Square();
console.log(MySquare.className); // "Square"

答案 3 :(得分:17)

更新

确切地说,我认为OP要求一个函数来检索特定对象的构造函数名称。就Javascript而言,object没有类型,但类型本身。但是,不同的对象可以有不同的构造函数

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"


注意:以下示例已弃用。

blog post链接的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

答案 4 :(得分:12)

使用Object.prototype.toString

事实证明,正如本文详细介绍的那样,您可以使用Object.prototype.toString(toString的低级和泛型实现)来获取所有内置类型的类型

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

可以编写一个简短的辅助函数,例如

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

答案 5 :(得分:9)

这是我提出的一个解决方案,解决了instanceof的缺点。它可以从跨窗口和跨帧检查对象的类型,并且没有原始类型的问题。

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需要两个参数:对象和类型。它如何工作的真正技巧是它检查对象是否来自同一个窗口,如果没有得到对象的窗口。

示例:

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参数也可以是一个返回构造函数的回调函数。回调函数将接收一个参数,该参数是所提供对象的窗口。

示例:

//"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&lt; 9没有在所有对象上提供构造函数,因此NodeList的上述测试将返回false,并且isInstance(alert,“Function”)将返回false。

答案 6 :(得分:7)

我实际上是在寻找类似的东西并遇到了这个问题。以下是我获取类型的方式: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);
}

答案 7 :(得分:6)

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

  • 继承树中最接近的原型
  • 用于始终原始类型,例如'null'和'undefined',原始名称。

它适用于所有JS对象和基元,无论它们是如何创建的,并且没有任何意外。例子:

数字

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'

字符串

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'

答案 8 :(得分:6)

尽可能使用constructor.name,当我不能时使用正则表达式。

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

答案 9 :(得分:5)

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

答案 10 :(得分:3)

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

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运算符显示的信息有限。一种解决方案是使用Object全局对象的toString()方法。例如,如果你有一个对象,比如myObject,你可以使用全局Object的toString()方法来确定myObject类的类型。使用此:

Object.prototype.toString.apply(myObject);

答案 11 :(得分:3)

以下是基于the accepted answer的实现:

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

当我们别无选择时,我们只使用构造函数属性。

答案 12 :(得分:2)

最接近的是typeof,但它只返回任何类型的自定义类型的“对象”。对于那些,请参阅Jason Bunting

编辑,Jason因某种原因删除了他的帖子,所以只需使用Object的constructor属性。

答案 13 :(得分:2)

您应该像使用somevar.constructor.name一样

    
    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'

答案 14 :(得分:1)

说你有$ mysqladmin ping -u root /junk/mysqladmin.orig: connect to server at 'localhost' failed error: 'Access denied for user 'root'@'localhost' (using password: NO)' $ mysqladmin ping -u myuser mysqld is alive $ mysqladmin ping /junk/mysqladmin.orig: connect to server at 'localhost' failed error: 'Access denied for user 'root'@'localhost' (using password: NO)'

如果您只想要obj类型的名称,例如“Object”,“Array”或“String”, 你可以用这个:

$ mysqladmin ping -u root
/junk/mysqladmin.orig: connect to server at 'localhost' failed
error: 'Access denied for user 'root'@'localhost' (using password: NO)'

$ mysqladmin ping -u myuser
mysqld is alive

$ mysqladmin ping
mysqld is alive

答案 15 :(得分:1)

非常简单!

  • 我最喜欢的在JS中获取任何类型的方法
function getType(entity){
    var x = Object.prototype.toString.call(entity)
    return x.split(" ")[1].split(']')[0].toLowerCase()
}
  • 我最喜欢的检查JS中任何内容类型的方法
function checkType(entity, type){
    return getType(entity) === type
}

答案 16 :(得分:0)

如果有人在寻找与jQuery一起使用的解决方案,那么这是经过调整的维基代码(原来打破了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] : "";
    }
});

答案 17 :(得分:0)

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

它为lodash添加了一种名为&#34;识别&#34;其工作原理如下:

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

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

答案 18 :(得分:0)

好的,伙计们,我已经慢慢建立一个捕捉所有方法,这几年多哈!诀窍是:

      
  1. 有一个创建类的机制。
  2.   
  3. 有一种机制可以检查由本机构造函数创建/生成的所有用户创建的类,基元和值。
  4.   
  5. 有一种机制可以将用户创建的类扩展为新的类,以便上述功能渗透到您的代码/应用程序/库/等中。
  6. 举个例子(或者看看我是如何处理这个问题的),在github上查看以下代码:https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js并搜索:

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

    正如您所看到的,我有一些机制可以强制classOf始终为我提供类/构造函数类型名称,无论它是基元,用户定义的类,使用本机构造函数创建的值,Null,NaN等。对于每个javascript值,我将从classOf函数中获取它的唯一类型名称。另外我可以将实际构造函数传递给sjl.classOfIs来检查值的类型,以及能够传递它的类型名称!例如:

    ```     //请原谅长名称空间!直到使用它们一段时间之后我才知道它的影响(它们吸吮哈哈)

    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`!
    

    ```

    如果您有兴趣详细了解我如何使用上述设置,请查看回购:https://github.com/elycruz/sjljs

    还有关于该主题的内容的书籍: - Stoyan Stefanov的“JavaScript Patterns”。 - “Javascript - The Definitive Guide”。作者:David Flanagan。 - 还有很多其他..(搜索le`网页)。

    此外,您可以快速测试我在这里谈论的功能: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/(url中的0.5.18路径也有来自github的源减去node_modules等等。)

    快乐的编码!

答案 19 :(得分:0)

使用class.name。这也适用于function.name

class TestA {}
console.log(TestA.name); // "TestA"

function TestB() {}
console.log(TestB.name); // "TestB"

答案 20 :(得分:0)

对于那些阅读本文并想要一个运行良好且经过测试的简单解决方案的人:

const getTypeName = (thing) => {
  const name = typeof thing
  if (name !== 'object') return name
  if (thing instanceof Error) return 'error'
  if (!thing) return 'null'
  return ({}).toString.call(thing).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

要深入了解其工作原理,请查看 Array.isArray() 的 polyfill 文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#polyfill