我如何在JavaScript中获取对象类型的名称?

有没有Java的class.getName()的JavaScript等价物?


有没有Java的class.getName()的JavaScript等价物?

没有

ES2015更新class Foo {}的名称是Foo.name 。 名称thing的类,不管thing的类型,是thing.constructor.name 。 ES2015环境中的内建构造函数具有正确的name属性; 例如(2).constructor.name"Number"


但是,这里有各种各样的黑客以各种方式跌倒:

这里有一个破解你需要的东西 - 注意它修改了对象的原型,让人们皱眉(通常是出于很好的理由)

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

现在,您的所有对象都将具有getName()函数,它将以字符串的形式返回构造函数的名称。 我已经在FF3IE7测试过了,我不能说其他的实现。

如果你不想这样做,下面是关于在JavaScript中确定类型的各种方法的讨论...


我最近更新了这个更详尽的内容,尽管这很难。 更正欢迎...

使用constructor属性...

每个object都有其constructor属性的值,但取决于该object构造方式以及要使用该值执行的操作,它可能有用,也可能没用。

一般来说,您可以使用constructor属性来测试对象的类型,如下所示:

var myArray = [1,2,3];
(myArray.constructor == Array); // true

所以,对于大多数需求来说,这样做足够好。 那说...

注意事项

在许多情况下,都不会起作用

这种模式虽然破损,但相当普遍:

function Thingy() {
}
Thingy.prototype = {
    method1: function() {
    },
    method2: function() {
    }
};

通过new Thingy构造的Objects将具有指向Objectconstructor属性,而不是Thingy 。 所以我们一开始就落后; 你不能信任你不能控制的代码库中的constructor

多重继承

一个不太明显的例子是使用多重继承:

function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a

现在事情并不像你期望的那样工作:

var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true

所以,你可能会得到意想不到的结果,如果object您的测试有不同的object设置为其prototype 。 这个讨论的范围之外有办法解决这个问题。

constructor属性还有其他用途,其中一些有趣,其他则不多; 现在我们不会深入研究这些用途,因为它与本次讨论无关。

不会跨越框架和跨窗口工作

当您想要检查来自不同window对象的对象的类型时,使用.constructor进行类型检查会中断,比如iframe或弹出窗口。 这是因为每个“窗口”中的每个核心类型constructor都有不同的版本,即

iframe.contentWindow.Array === Array // false

使用instanceof操作符...

instanceof运算符也是测试object类型的干净方式,但它有自己的潜在问题,就像constructor属性一样。

var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true

但是instanceof不能用于字面值(因为文字不是Objects

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false

例如,文字需要包装在一个Object中,以便instanceof工作

new Number(3) instanceof Number // true

.constructor检查工作正常的文字,因为. 方法调用隐式地将文字包装在它们各自的对象类型中

3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true

为什么两个点为3? 因为Javascript将第一个点解释为小数点;)

不会跨越框架和跨窗口工作

instanceof也不能在不同的窗口中工作,这与constructor属性检查的原因相同。


使用constructor属性的name属性...

在许多情况下都不起作用

再次,见上文; constructor完全错误和无用是很常见的。

在<IE9中不起作用

使用myObjectInstance.constructor.name将为您提供一个字符串,其中包含所使用的constructor函数的名称,但受限于前面提到的有关constructor属性的警告。

对于IE9及以上版本,您可以支持猴子补丁:

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /functions+([^s(]+)s*(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1] : "";
        },
        set: function(value) {}
    });
}

相关文章的更新版本 。 这是在文章发表3个月后添加的,这是该文章作者Matthew Scharley推荐使用的版本。 这个改变受到了评论的启发,指出了前面代码中的潜在缺陷。

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /functions([^(]{1,})(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1].trim() : "";
        },
        set: function(value) {}
    });
}

使用Object.prototype.toString

事实证明,正如这篇文章的细节,您可以使用Object.prototype.toStringtoString的低级别和通用实现)来获取所有内置类型的类型

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).slice(8, -1);
}

删除cruft并得到只是类型的名称

type('abc') // String

但是,它将为所有用户定义的类型返回Object


所有人的注意事项...

所有这些都有一个潜在的问题,那就是这个问题是如何构建的。 以下是构建对象的各种方法以及类型检查的不同方法将返回的值:

// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // true
(obj.constructor.name == "Foo");  // true

// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // false
(obj.constructor.name == "Foo");  // false


// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object);              // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == "");         // true


// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object);      // true
(obj instanceof Foo);         // true
(obj.constructor == Foo);     // true
(obj.constructor.name == ""); // true


// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object);            // true
(obj.constructor == Object);        // true
(obj.constructor.name == "Object"); // true

虽然并不是所有的排列都出现在这组示例中,但希望能够为您提供一个关于如何根据您的需求获得混乱的东西的想法。 不要假设任何事情,如果你不能完全理解你的想法,那么你可能会因为缺乏对细节的缺乏而期望的代码断裂。

注意:

在讨论typeof运营商可能似乎是一个明显的遗漏,但它确实是不是在帮助识别是否有用的object是给定类型,因为它是非常简单的。 了解typeof的用处很重要,但我目前并不认为这与此讨论非常相关。 尽管我的想法可以改变。 :)


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

<<Object instance>>.constructor.name

所以,例如,在下面的一段代码中:

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

myInstance.constructor.name将返回"MyObject"


我使用的一个小技巧:

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

var MySquare = new Square();
console.log(MySquare.className); // "Square"
链接地址: http://www.djcxy.com/p/46175.html

上一篇: How do I get the name of an object's type in JavaScript?

下一篇: How to delay the .keyup() handler until the user stops typing?