如何获取JavaScript对象的类?


728

我创建了一个JavaScript对象,但是如何确定该对象的类呢?

我想要类似Java的.getClass()方法。


6
例如,我使人像这样:var p = new Person(); 我有一个名为“ p”的Person对象,如何使用“ p”取回类名称:“ Person”。
DNB5brims


更新:从ECMAScript 6开始,JavaScript仍然没有class类型。它确实具有用于创建原型的class关键字和class语法,可以在其中更轻松地访问方法super
james_womack '16

那Object.className呢?
Paul Basenko

@ Paul-Basenko:“ className”不会告诉您对象的类,但会返回HTML元素的“ class”属性的内容,该属性引用CSS类。您还希望使用“ classList”轻松管理它们,但这与OP的问题无关。
黑曜石

Answers:


1009

getClass()JavaScript中没有Java的完全对应版本。通常,这是由于JavaScript是一种基于原型的语言,而不是Java是一种基于类的语言

根据您的需要getClass(),JavaScript中有几个选项:

一些例子:

function Foo() {}
var foo = new Foo();

typeof Foo;             // == "function"
typeof foo;             // == "object"

foo instanceof Foo;     // == true
foo.constructor.name;   // == "Foo"
Foo.name                // == "Foo"    

Foo.prototype.isPrototypeOf(foo);   // == true

Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21);            // == 42

注意:如果使用Uglify编译代码,它将更改非全局类名。为了防止这种情况,丑化有--manglePARAM,你可以设置为false使用一饮而尽呼噜声


6
可能应该是func.prototype(是的,函数是对象,但是prototype属性仅与函数对象相关)。
英里

5
您可能还想提及instanceof/ isPrototypeOf()和非标准__proto__
Christoph

9
ES5有方法,另外Object.getPrototypeOf()
克里斯托夫

22
警告constructor.name如果您的代码正在缩小,请不要依赖。函数名称将任意更改。
igorsantos

3
@ igorsantos07,至少在2019年; Google上“在线JavaScript缩小器”的前5-10个结果被construction.name认为是要忽略的令牌,而不是将其最小化。除了大多数(如果不是全部),minifier软件还提供例外规则。
vulcan raven

296
obj.constructor.name

在现代浏览器中是一种可靠的方法。Function.name已在ES6中正式添加到该标准中,从而使这成为将JavaScript对象的“类”作为字符串获取的符合标准的方法。如果对象被实例化var obj = new MyClass(),它将返回“ MyClass”。

它将为数字返回“ Number”,为数组返回“ Array”,为函数返回“ Function”,等等。它的行为通常与预期的一样。失败的唯一情况是通过原型创建了没有原型Object.create( null )的对象,或者该对象是从匿名定义(未命名)的函数实例化的。

还要注意,如果要压缩代码,则与硬编码类型字符串进行比较是不安全的。例如,不检查是否obj.constructor.name == "MyType",而是检查obj.constructor.name == MyType.name。或者只是比较构造函数本身,但是这将无法跨DOM边界,因为每个DOM上都有不同的构造函数实例,因此无法在其构造函数上进行对象比较。


11
Function.name还不是JavaScript标准的一部分。Chrome和Firefox当前支持该功能,但IE(10)不支持。
Halcyon

13
obj.constructor.name仅适用于命名函数。即,如果我定义var Foo = function() {},则for var foo = new Foo()foo.constructor.name将为您提供空字符串。
KFL 2014年

29
警告constructor.name如果您的代码正在缩小,请不要依赖。函数名称将任意更改。
igorsantos


1
@adalbertpl在ES6之前,它与手动链接原型有关。很高兴知道constructor.nameES6中的新类支持行为符合预期。
devios1

29

此函数返回"Undefined"未定义的值和"Null"null。
对于所有其他值,CLASSNAME-part是从中提取的[object CLASSNAME],这是使用的结果Object.prototype.toString.call(value)

function getClass(obj) {
  if (typeof obj === "undefined") return "Undefined";
  if (obj === null) return "Null";
  return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}

getClass("")   === "String";
getClass(true) === "Boolean";
getClass(0)    === "Number";
getClass([])   === "Array";
getClass({})   === "Object";
getClass(null) === "Null";
// etc...

使用'this'而不是obj的Object.prototype.getClass = function(){很不错
SparK 2012年

2
当然,因为只有对象才具有getClass方法
所以

8
这仅适用于本机对象。如果您拥有某种继承权,您将永远得到"Object"
Halcyon

是的,函数的最后一行应该是return obj.constructor.name。这样可以得到相同的结果,并且还可以处理非本机对象。
史蒂夫·贝内特

18

要获取“伪类”,您可以通过以下方式获取构造函数

obj.constructor

假设constructor在进行继承时已正确设置-这是类似的:

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

这两行,以及:

var woofie = new Dog()

woofie.constructor指向Dog。请注意,它Dog是一个构造函数,并且是一个Function对象。但是你可以if (woofie.constructor === Dog) { ... }

如果您想以字符串形式获取类名,我发现以下方法运行良好:

http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects

function getObjectClass(obj) {
    if (obj && obj.constructor && obj.constructor.toString) {
        var arr = obj.constructor.toString().match(
            /function\s*(\w+)/);

        if (arr && arr.length == 2) {
            return arr[1];
        }
    }

    return undefined;
}

它到达构造函数,将其转换为字符串,并提取构造函数的名称。

请注意,这obj.constructor.name可能效果很好,但这不是标准的。它可以在Chrome和Firefox上使用,但不能在IE(包括IE 9或IE 10 RTM)上使用。


13

您可以使用构造函数属性获取对创建对象的构造函数的引用:

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

如果需要在运行时确认对象的类型,则可以使用instanceof运算符:

obj instanceof MyObject // true

它不返回构造函数本身,例如,您可以再次调用它并创建该类型的新对象吗?
SparK'1

1
@SparK是的,尽管只要您在同一DOM上(正在比较功能对象),您仍然可以使用它进行比较。但是,将构造函数转换为字符串并进行比较是一种更好的做法,特别是因为在使用iframe时,它可以跨DOM边界工作。
devios1 2012年

该答案返回“类”(或至少一个可用于创建该类实例的对象的句柄-与“该类”相同)。上面的代码回答了所有返回的字符串,这些字符串与“类对象”不同(原样)。
Mike P.

8

为了保持其向后兼容的不间断记录ECMAScript 6,JavaScript仍然没有class类型(尽管不是每个人都理解这一点)。它确实在创建原型时将class关键字作为其class语法的一部分,但仍然没有一个叫做class的东西。JavaScript现在不是,并且从来都不是经典的OOP语言。从类的角度讲JS只是一种误导,或者是尚未取消原型继承的迹象(只是保持它的真实性)。

这意味着this.constructor仍然是引用该constructor函数的好方法。并且this.constructor.prototype是访问原型本身的方法。由于这不是Java,所以它不是类。这是实例从中实例化的原型对象。这是一个使用ES6语法糖创建原型链的示例:

class Foo {
  get foo () {
    console.info(this.constructor, this.constructor.name)
    return 'foo'
  }
}

class Bar extends Foo {
  get foo () {
    console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
    console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))

    return `${super.foo} + bar`
  }
}

const bar = new Bar()
console.dir(bar.foo)

这是使用babel-node以下命令输出的内容:

> $ babel-node ./foo.js                                                                                                                    6.2.0 master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'

你有它!在2016年,classJavaScript中有一个关键字,但仍然没有类类型。this.constructor是获取构造函数this.constructor.prototype的最佳方法,也是访问原型本身的最佳方法。


7

我现在有一种情况可以通用工作,并使用了以下方法:

class Test {
  // your class definition
}

nameByType = function(type){
  return type.prototype["constructor"]["name"];
};

console.log(nameByType(Test));

如果您没有对象的实例,那就是我发现通过类型输入获取类名称的唯一方法。

(用ES2017编写)

点符号也可以

console.log(Test.prototype.constructor.name); // returns "Test" 

啊,这就是我想要的。如果未实例化,则必须使用“原型”来获取类名称。万分感谢!
Artokun

4

对于ES6中的Javascript类,可以使用object.constructor。在下面的示例类中,该getClass()方法返回您期望的ES6类:

var Cat = class {

    meow() {

        console.log("meow!");

    }

    getClass() {

        return this.constructor;

    }

}

var fluffy = new Cat();

...

var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();

ruffles.meow();    // "meow!"

如果从getClass方法实例化该类,请确保将其包装在方括号中,例如ruffles = new ( fluffy.getClass() )( args... );


3

我在IE中找到object.constructor.toString()返回[object objectClass],而不是function objectClass () {}在chome中返回。因此,我认为http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects中的代码在IE中可能无法正常工作。我将代码修复如下:

码:

var getObjectClass = function (obj) {
        if (obj && obj.constructor && obj.constructor.toString()) {

                /*
                 *  for browsers which have name property in the constructor
                 *  of the object,such as chrome 
                 */
                if(obj.constructor.name) {
                    return obj.constructor.name;
                }
                var str = obj.constructor.toString();
                /*
                 * executed if the return of object.constructor.toString() is 
                 * "[object objectClass]"
                 */

                if(str.charAt(0) == '[')
                {
                        var arr = str.match(/\[\w+\s*(\w+)\]/);
                } else {
                        /*
                         * executed if the return of object.constructor.toString() is 
                         * "function objectClass () {}"
                         * for IE Firefox
                         */
                        var arr = str.match(/function\s*(\w+)/);
                }
                if (arr && arr.length == 2) {
                            return arr[1];
                        }
          }
          return undefined; 
    };

2

在javascript中,没有任何类,但是我认为您需要构造函数名称,obj.constructor.toString()并将告诉您所需的内容。


1
这将以字符串形式返回构造函数的整个定义。你真正想要的是.name
devios1 2012年

4
.name即使在IE 9上也没有定义
极性

1

同意dfa,这就是为什么在找不到命名类的情况下我将原型视为该类的原因

这是Eli Grey发布的功能的升级功能,以符合我的想法

function what(obj){
    if(typeof(obj)==="undefined")return "undefined";
    if(obj===null)return "Null";
    var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
    if(res==="Object"){
        res = obj.constructor.name;
        if(typeof(res)!='string' || res.length==0){
            if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
            if(obj instanceof Array)return "Array";// Array prototype is very sneaky
            return "Object";
        }
    }
    return res;
}

1

如果您不仅需要GET类,还需要仅通过一个实例来扩展它,请编写:

让我们

 class A{ 
   constructor(name){ 
     this.name = name
   }
 };

 const a1 = new A('hello a1');

因此扩展具有实例的A仅使用:

const a2 = new ((Object.getPrototypeOf(a)).constructor())('hello a2')
// the analog of const a2 = new A()

console.log(a2.name)//'hello a2'

0

我建议使用Object.prototype.constructor.name

Object.defineProperty(Object.prototype, "getClass", {
    value: function() {
      return this.constructor.name;
    }
});

var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'

var y = new Error("");
console.log(y.getClass()); // `Error'

0

这是getClass()和的实现getInstance()

您可以使用来获取对象类的引用this.constructor

从实例上下文中:

function A() {
  this.getClass = function() {
    return this.constructor;
  }

  this.getNewInstance = function() {
    return new this.constructor;
  }
}

var a = new A();
console.log(a.getClass());  //  function A { // etc... }

// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true

从静态上下文:

function A() {};

A.getClass = function() {
  return this;
}

A.getInstance() {
  return new this;
}

2
为什么不只是this.constructor呢?
所罗门·乌科2016年

1
我不知道,但是如果更好,您肯定可以编辑答案,以发现更好的答案,毕竟这是一个社区。
Bruno Finger

0

你也可以做这样的事情

 class Hello {
     constructor(){
     }
    }
    
      function isClass (func) {
        return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
    }
    
   console.log(isClass(Hello))

这将告诉您输入是否为类


-2

Javascript是一种无类语言:没有类可以像Java中一样静态地定义类的行为。JavaScript使用原型而不是类来定义对象属性,包括方法和继承。使用JavaScript中的原型可以模拟许多基于类的功能。


12
我经常说Javascript缺少课程:)
史蒂文(Steven)

4
更新:从ECMAScript 6开始,JavaScript仍然没有class类型。它确实具有用于创建原型的class关键字和class语法,可以在其中更轻松地访问方法super
james_womack

-3

问题似乎已经回答了,但OP希望访问和对象的类,就像我们在Java中所做的那样,所选答案还不够(恕我直言)。

通过以下解释,我们可以获得对象的类(实际上在javascript中称为原型)。

var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');

您可以添加如下属性:

Object.defineProperty(arr,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue

但是.last属性仅可用于arr从Array原型实例化的' '对象。因此,为了使该.last属性可用于从Array原型实例化的所有对象,我们必须定义.lastArray原型的属性:

Object.defineProperty(Array.prototype,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

这里的问题是,您必须知道' arr'和' arr2'变量属于哪个对象类型(原型)!换句话说,如果您不知道' arr'对象的类类型(原型),则将无法为其定义属性。在上面的示例中,我们知道arr是Array对象的实例,这就是为什么我们使用Array.prototype为Array定义属性的原因。但是,如果我们不知道' arr' 的类(原型)怎么办?

Object.defineProperty(arr.__proto__,'last2', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

如您所见,在不知道arr'是数组的情况下,我们可以arr通过使用' 引用' ' 的类来添加新属性。arr.__proto__ '。

我们访问了'的原型,arr却不知道它是Array的一个实例,我认为这就是OP的要求。


__proto__属性已弃用,并且几乎没有任何优势prototype
Sapphire_Brick
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.