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

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


在JavaScript中没有与Java的getClass()完全对应的方法。这主要是因为JavaScript是基于原型的语言,而Java是基于类的语言。

根据你需要getClass()做什么,JavaScript中有几个选项:

typeof 运算符 obj.constructor 函数。原型,proto.isPrototypeOf

举几个例子:

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参数,你可以使用gulp或grunt将其设置为false。


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


你可以通过使用constructor属性获取创建对象的构造函数的引用:

function MyObject(){
}

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

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

obj instanceof MyObject // true

在javascript中,没有类,但我认为您需要构造函数名称和obj.constructor.toString()将告诉您需要什么。


这个getNativeClass()函数对于未定义的值返回“undefined”,对于空值返回“null”。对于所有其他值,CLASSNAME-part从[object CLASSNAME]中提取,这是使用object .prototype. tostring .call(value)的结果。

getAnyClass()的行为与gettnativeclass()相同,但也支持自定义构造函数

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

function getAnyClass(obj) {
  if (typeof obj === "undefined") return "undefined";
  if (obj === null) return "null";
  return obj.constructor.name;
}

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

getAnyClass(new (function Foo(){})) === "Foo";
getAnyClass(new class Foo{}) === "Foo";

// etc...

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


要获得“伪类”,可以通过获取构造函数

obj.constructor

假设在你进行继承时构造函数被正确地设置了——就像这样:

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

这两行,加上:

var woofie = new Dog()

会做出伍菲。构造器指向狗。注意,Dog是一个构造函数,是一个function对象。但是你可以这样做,如果。构造函数=== 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。


我发现object.constructor. tostring()在IE中返回[object objectClass],而不是在chome中返回函数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; 
    };
    

同意dfa,这就是为什么我认为原型类,当没有命名类发现

下面是伊莱·格雷发布的一个升级版功能,以匹配我的思维方式

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

下面是getClass()和getInstance()的实现

你可以使用this.constructor获取Object类的引用。

从实例上下文:

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

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


为了保持ECMAScript 6一贯的向后兼容性,JavaScript仍然没有类类型(尽管不是每个人都理解这一点)。它确实有一个class关键字作为创建原型的类语法的一部分——但仍然没有称为class的东西。JavaScript现在不是,也从来都不是经典的OOP语言。从类的角度来谈论JS要么是一种误导,要么是一种还没有找到原型继承的迹象(只是保持它的真实)。

这意味着。构造函数仍然是获取构造函数引用的好方法。这个。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。prototype是访问原型本身的最佳方式。


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

通过下面的解释,我们可以得到一个对象的类(实际上在javascript中称为prototype)。

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属性将只对从Array原型实例化的'arr'对象可用。因此,为了使.last属性对所有从Array prototype实例化的对象可用,我们必须为Array prototype定义.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.__proto__'引用'arr'的类即可。

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


我现在有一个通用的情况,使用这个:

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" 

我建议使用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'

你也可以这样做

Hello { 构造函数(){ } } 函数isClass (func) { 返回typeof func === 'function' && /^class\s/.test(function .prototype. tostring .call(func)) } console.log (isClass(你好))

这将告诉您输入是否是类


如果你不仅需要GET类,还需要EXTEND类,这样写:

让我们来

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

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

因此扩展A只使用实例:

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

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

还有另一种技术可以识别类 你可以像下面这样在实例中存储引用到你的类。

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

我们可以通过执行'instance.constructor.name'来读取实例的Class名,如下例所示:

class Person {
  type = "developer";
}
let p = new Person();

p.constructor.name // Person

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

我找到了一种方法来访问类,比上面的一些解决方案要干净得多;在这儿。

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 access的属性,它将为您提供类名。

更简洁的代码版本:

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

如果你可以访问类Foo的实例(Foo = new Foo()),那么只有一种方法可以从实例中访问类:Foo。Javascript中的构造函数= Java中的foo.getClass()。

eval()是另一种方法,但由于eval()永远不被推荐,它适用于所有事情(类似于Java反射),所以不推荐使用这种方法。foo。构造函数= Foo


不要使用o.constructor,因为它可以被对象内容改变。相反,使用Object.getPrototypeOf()?.constructor。

const fakedArray = JSON.parse('{ "constructor": { "name": "Array" } }');

// returns 'Array', which is faked.
fakedArray.constructor.name;

// returns 'Object' as expected
Object.getPrototypeOf(fakedArray)?.constructor?.name;