如何获得JavaScript对象的类?

时间:2009-08-08 18:11:57

标签: javascript oop

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

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

21 个答案:

答案 0 :(得分:840)

JavaScript中的getClass()没有确切的对应物。主要是因为JavaScript是prototype-based language,而Java则是class-based

根据您的需要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编译代码,它将更改非全局类名。为防止这种情况发生,Uglify有一个--mangle参数,您可以设置为false,使用gulpgrunt

答案 1 :(得分:244)

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上有不同的构造函数实例,因此在它们的构造函数上进行对象比较将不起作用。

在链接原型时注意

编辑:现在,ES6对类和继承有更好的支持,这显然没有实际意义。正如adalbertpl所解释的那样,constructor.name在这种情况下表现得如预期的那样。

奇怪的是,constructor.name返回原型链中使用的最基本函数的名称,遗憾的是这不是直观的。例如,如果BA原型推导出来并且您创建B的新实例,b,则b.constructor.name会返回“A”,这似乎是错误的。然而,它确实适用于单级原型和所有基元。

答案 2 :(得分:27)

此函数从"undefined"返回"null""class"[object class]中的Object.prototype.toString.call(someObject)

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

答案 3 :(得分:17)

要获取“伪类”,可以通过

获取构造函数
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。

答案 4 :(得分:10)

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

function MyObject(){
}

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

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

obj instanceof MyObject // true

答案 5 :(得分:4)

为了保持其完整的向后兼容记录ECMAScript 6,JavaScript仍然没有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年,JavaScript中有一个class关键字,但仍然没有类类型。 this.constructor是获取构造函数的最佳方法,this.constructor.prototype是访问原型本身的最佳方式。

答案 6 :(得分:4)

我现在有一种情况可以使用通用并使用它:

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" 

答案 7 :(得分:3)

我发现object.constructor.toString()在IE中返回[object objectClass],而不是在chome中返回function objectClass () {}。所以,我认为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; 
    };

答案 8 :(得分:3)

对于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... );

答案 9 :(得分:2)

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

答案 10 :(得分:1)

同意dfa,这就是我没有找到命名类时将原型视为类的原因

以下是Eli Gray发布的升级版功能,以配合我的心态

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

答案 11 :(得分:1)

我们可以通过像这个例子中的'instance.constructor.name'来读取实例的类名:

UPDATE employees SET id_employee=13 WHERE name='Wick' AND surname='John';

答案 12 :(得分: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'

答案 13 :(得分:0)

getClass() 函数使用 constructor.prototype.name

我找到了一种访问 class 的方法,它比上面的一些解决方案更简洁;在这里。

function getClass(obj) {

   // if the type is not an object return the type
   if((let type = typeof obj) !== 'object') return type; 
    
   //otherwise, access the class using obj.constructor.name
   else return obj.constructor.name;   
}

工作原理

构造函数有一个名为 name 的属性,它会为您提供类名。

更清晰的代码版本:

function getClass(obj) {

   // if the type is not an object return the type
   let type = typeof obj
   if((type !== 'object')) { 
      return type; 
   } else { //otherwise, access the class using obj.constructor.name
      return obj.constructor.name; 
   }   
}

答案 14 :(得分:0)

还有另一种识别班级的技术 您可以在下面的实例中将ref存储到您的类中。

class MyClass {
    static myStaticProperty = 'default';
    constructor() {
        this.__class__ = new.target;
        this.showStaticProperty = function() {
            console.log(this.__class__.myStaticProperty);
        }
    }
}

class MyChildClass extends MyClass {
    static myStaticProperty = 'custom';
}

let myClass = new MyClass();
let child = new MyChildClass();

myClass.showStaticProperty(); // default
child.showStaticProperty(); // custom

myClass.__class__ === MyClass; // true
child.__class__ === MyClass; // false
child.__class__ === MyChildClass; // true

答案 15 :(得分:0)

您也可以这样做

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

这将告诉您输入是否为班级

答案 16 :(得分: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'

答案 17 :(得分:0)

尝试我的图书馆typescript-class-helpers

import { CLASS } from 'typescript-class-helpers'

@CLASS.NAME('Example')
class Example {

}

console.log(CLASS.getName(Example) === 'Example') // true
console.log(CLASS.getNameFromObject(new Example()) === 'Example') // true
console.log(CLASS.getBy('Example') === Example) // true

这样,即使经过丑化处理,您也可以使用类名。

安装:

npm i typescript-class-helpers

答案 18 :(得分:0)

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

答案 19 :(得分:-1)

这是consumesgetClass()

的实现

您可以使用getInstance()获取对象类的参考。

从实例上下文:

window

来自静态环境:

function A() {
    this.getClass = function() {
        return window[this.constructor.name];
    }

    this.getNewInstance = function() {
        return new window[this.constructor.name];
    }
}

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

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

答案 20 :(得分:-2)

问题似乎已经得到解答,但OP想要访问类和对象,就像我们在Java中所做的那样,选择的答案还不够(imho)。

通过以下说明,我们可以获得一个对象的类(它实际上在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原型实例化的所有对象,我们必须为Array原型定义.last属性:

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__“的类”。

我们在不知道它是Array的实例的情况下访问了'arr'的原型,我认为这就是OP所要求的。