ChatGPT解决这个技术问题 Extra ChatGPT

如何获取 JavaScript 对象的类?

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

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

例如,我创建了一个这样的人: var p = new Person();我有一个名为“p”的人对象,我如何使用“p”来取回类名:“人”。
更新:从 ECMAScript 6 开始,JavaScript 仍然没有 class 类型。它确实具有用于创建原型的 class 关键字和 class 语法,其中方法可以更轻松地访问 super
Object.className 呢?
@Paul-Basenko:“className”不会告诉您对象的类,但会返回 HTML 元素的“类”属性的内容,该属性指的是 CSS 类。您还想使用“classList”轻松管理它们,但这与 OP 的问题无关。

J
James L.

JavaScript 中没有与 Java 的 getClass() 完全对应的内容。这主要是因为 JavaScript 是 prototype-based language,而 Java 是 class-based

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

类型

实例

obj.constructor

func.prototype, 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 参数,您可以设置为 false 使用 gulpgrunt


那应该是 func.prototype(是的,函数是对象,但 prototype 属性仅与函数对象相关)。
您可能还想提及 instanceof/isPrototypeOf() 和非标准的 __proto__
ES5 还有 Object.getPrototypeOf()
警告:如果您的代码正在缩小,请不要依赖 constructor.name。函数名称将任意更改。
@igorsantos07,至少在 2019 年; “在线 javascript minifier”的前 5-10 个 google 结果将 construction.name 识别为要忽略/不最小化的令牌。此外,大多数(如果不是全部)缩小器软件都提供异常规则。
d
devios1
obj.constructor.name

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

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

另请注意,如果您正在缩小代码,则与硬编码类型字符串进行比较是不安全的。例如,不检查 if obj.constructor.name == "MyType",而是检查 obj.constructor.name == MyType.name。或者只是比较构造函数本身,但这不会跨越 DOM 边界,因为每个 DOM 上有不同的构造函数实例,因此对它们的构造函数进行对象比较是行不通的。


Function.name (还)不是 JavaScript 标准的一部分。目前在 Chrome 和 Firefox 中受支持,但在 IE(10) 中不支持。
Object.create(something).constructor === something.constructor,这也不完全正确。所以 obj.constructor 对于所有用 Object.create 制作的对象都是不可靠的,不管有没有原型。
警告:如果您的代码正在缩小,请不要依赖 constructor.name。函数名称将任意更改。
Function.name 是 ES6 的一部分,请参阅 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@adalbertpl 它与 ES6 之前的手动链接原型有关。很高兴知道 constructor.name 在 ES6 中的新类支持下的行为符合预期。
E
Eli Grey

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

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

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

Object.prototype.getClass = function(){ 使用 'this' 而不是 obj 会很好
当然,然后 null 和 undefined 将是不可检查的,因为只有 Object 会有 getClass 方法
这仅适用于本机对象。如果你有某种继承,你总是会得到 "Object"
是的,函数的最后一行应该是 return obj.constructor.name。这给出了相同的结果,而且还处理非本机对象。
M
Maksym Dudyk

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

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

p.constructor.name // Person

n
nonopolarity

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

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。


你得到了woofie的积分。
C
Christian C. Salvadó

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

function MyObject(){
}

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

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

obj instanceof MyObject // true

它不返回构造函数本身吗,例如,您可以再次调用它并创建该类型的新对象?
@SparK是的,尽管只要您在同一个DOM上(您正在比较函数对象),您仍然可以使用它进行比较。然而,将构造函数转换为字符串并进行比较是更好的做法,特别是因为在使用 iframe 时它可以跨 DOM 边界工作。
这个答案返回“类”(或至少一个句柄可用于创建类的实例的对象 - 这与“类”相同)。以上回答了所有与“类对象”不同的返回字符串(原样)。
m
mtizziani

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

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" 

啊,这就是我要找的。如果它没有被实例化,你必须使用'prototype'来获取类名。万分感谢!
j
james_womack

为了保持其向后兼容的完整记录,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 是获取原型本身的最佳方式。


H
Hugheth

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


l
lucian.pantelimon

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


这会将构造函数的整个定义作为字符串返回。您真正想要的是 .name
但即使在 IE 9 上也没有定义 .name
C
Community

我在 IE 中发现 object.constructor.toString() 返回 [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; 
    };
    

A
Ahmed Rahmi

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

我找到了一种访问 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; 
   }   
}

上面的评论:“警告:如果您的代码被缩小,请不要依赖 constructor.name。函数名称将任意更改。”
A
Alexey Nikonov

如果您不仅需要 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'

A
Antkhan

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

S
Sapphire_Brick

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

C
Community

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

为什么不只是 this.constructor
我不知道,但如果它更好,你绝对可以编辑答案以改进它,因为你发现更好,毕竟这是一个社区。
i
iRohitBhatia

你也可以做这样的事情

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

这将告诉您输入是否为类


d
dfa

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


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

还有另一种技术可以识别您的类您可以在下面的实例中将 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

r
ramazan polat

问题似乎已经得到解答,但 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 属性仅可用于从 Array 原型实例化的“arr”对象。因此,为了使 .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.__proto__”添加一个新属性,只需引用“arr”的类即可。

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


__proto__ 属性已被弃用,与 prototype 属性相比几乎没有优势。