是否有一个JavaScript的等效的Java的class.getName()
?
获取对象类型的名称
是否有相当于 Java 的 JavaScript
class.getName()
?
没有。
ES2015 更新:名称class Foo {}
为Foo.name
. thing
无论thing
的类型如何, 的类的名称都是thing.constructor.name
。ES2015 环境中的内置构造函数具有正确的name
属性;例如(2).constructor.name
是"Number"
。
但是这里有各种各样的黑客,它们都以一种或另一种方式失败:
这是一个可以满足您需要的 hack - 请注意,它会修改对象的原型,这是人们不赞成的(通常有充分的理由)
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
现在,您的所有对象都将具有函数 ,getName()
它将以字符串形式返回构造函数的名称。我已经在FF3
和 中对此进行了测试IE7
,我不能说其他实现。
如果你不想这样做,这里是关于在 JavaScript 中确定类型的各种方法的讨论......
我最近更新了它,使其更加详尽,尽管事实并非如此。欢迎指正...
使用constructor
物业...
每个object
都有其constructor
属性的值,但取决于它的object
构造方式以及您想用该值做什么,它可能有用也可能没用。
一般来说,您可以使用该constructor
属性来测试对象的类型,如下所示:
var myArray = [1,2,3];
(myArray.constructor == Array); // true
因此,这足以满足大多数需求。那说...
注意事项
将无法正常工作在所有在许多情况下,
这种模式虽然被打破,但很常见:
function Thingy() {
}
Thingy.prototype = {
method1: function() {
},
method2: function() {
}
};
Objects
构造 vianew Thingy
将有一个constructor
属性指向Object
,而不是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
财产还有其他用途,其中一些很有趣,另一些则没有那么多;现在我们不会深入研究这些用途,因为它与本次讨论无关。
不能跨框架和跨窗口工作
.constructor
当您想要检查来自不同window
对象的对象类型时,例如 iframe 或弹出窗口的类型,使用for 类型检查将中断。这是因为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
文字需要包裹在 anObject
中才能instanceof
工作,例如
new Number(3) instanceof Number // true
该.constructor
检查适用于文字,因为.
方法调用隐式地将文字包装在它们各自的对象类型中
3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true
为什么 3 有两个点?因为 Javascript 将第一个点解释为小数点 ;)
不能跨框架和跨窗口工作
instanceof
也不会跨不同窗口工作,原因与constructor
属性检查相同。
使用name
物业的constructor
财产...
不工作在所有在许多情况下,
再次,见上文;constructor
完全错误和无用的情况是很常见的。
在 <IE9 中不起作用
UsingmyObjectInstance.constructor.name
将为您提供一个包含所constructor
使用函数名称的字符串,但受制于constructor
前面提到的有关该属性的警告。
对于 IE9 及更高版本,您可以使用猴子补丁支持:
if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
Object.defineProperty(Function.prototype, 'name', {
get: function() {
var funcNameRegex = /function\s+([^\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 = /function\s([^(]{1,})\(/;
var results = (funcNameRegex).exec((this).toString());
return (results && results.length > 1) ? results[1].trim() : "";
},
set: function(value) {}
});
}
使用 Object.prototype.toString
事实证明,作为这篇文章的详细信息,您可以使用Object.prototype.toString
- 的低级和通用实现toString
- 来获取所有内置类型的类型
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
操作符的讨论似乎是一个明显的遗漏,但它在帮助确定 a 是否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"
更新
准确地说,我认为 OP 要求一个函数来检索特定对象的构造函数名称。就 Javascript 而言,object
没有类型,但本身就是 和的类型。但是,不同的对象可以有不同的构造函数。
Object.prototype.getConstructorName = function () {
var str = (this.prototype ? this.prototype.constructor : this.constructor).toString();
var cname = str.match(/function\s(\w*)/)[1];
var aliases = ["", "anonymous", "Anonymous"];
return aliases.indexOf(cname) > -1 ? "Function" : cname;
}
new Array().getConstructorName(); // returns "Array"
(function () {})().getConstructorName(); // returns "Function"
注意:以下示例已弃用。
一个博客帖子的链接基督教Sciberras包含有关如何做一个很好的例子。即,通过扩展 Object 原型:
if (!Object.prototype.getClassName) {
Object.prototype.getClassName = function () {
return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1];
}
}
var test = [1,2,3,4,5];
alert(test.getClassName()); // returns Array
使用 Object.prototype.toString
事实证明,作为这篇文章的详细信息,您可以使用 Object.prototype.toString(toString 的低级和通用实现)来获取所有内置类型的类型
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]).match(/\s\w+/)[0].trim()
}
return [object String] as String
return [object Number] as Number
return [object Object] as Object
return [object Undefined] as Undefined
return [object Function] as Function