有JavaScript相当于Java的class.getName()
吗?
#1楼
Agave.JS的kind()函数将返回:
- 继承树中最接近的原型
- 对于总是原始类型(例如“ null”和“ undefined”)的原始名称。
无论它们如何创建 ,它都适用于所有JS对象和基元,并且没有任何惊喜。 例子:
号码
kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'
N
kind(NaN) === 'NaN'
弦乐
kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'
布尔值
kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'
数组
kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'
对象
kind({a:1}) === 'Object'
kind(new Object()) === 'Object'
日期
kind(new Date()) === 'Date'
职能
kind(function(){}) === 'Function'
kind(new Function("console.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'
未定义
kind(undefined) === 'undefined'
空值
kind(null) === 'null'
#2楼
我实际上正在寻找类似的东西,并遇到了这个问题。 这是我获取类型的方法: jsfiddle
var TypeOf = function ( thing ) {
var typeOfThing = typeof thing;
if ( 'object' === typeOfThing ) {
typeOfThing = Object.prototype.toString.call( thing );
if ( '[object Object]' === typeOfThing ) {
if ( thing.constructor.name ) {
return thing.constructor.name;
}
else if ( '[' === thing.constructor.toString().charAt(0) ) {
typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
}
else {
typeOfThing = thing.constructor.toString().match( /function\s*(\w+)/ );
if ( typeOfThing ) {
return typeOfThing[1];
}
else {
return 'Function';
}
}
}
else {
typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
}
}
return typeOfThing.charAt(0).toUpperCase() + typeOfThing.slice(1);
}
#3楼
如果有人在寻找可与jQuery一起使用的解决方案,请参阅以下经调整的Wiki代码(原始版本破坏了jQuery)。
Object.defineProperty(Object.prototype, "getClassName", {
value: function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}
});
#4楼
Lodash有很多isMethods,所以如果您使用Lodash,也许像这样的mixin可能会有用:
// Mixin for identifying a Javascript Object
_.mixin({
'identify' : function(object) {
var output;
var isMethods = ['isArguments', 'isArray', 'isArguments', 'isBoolean', 'isDate', 'isArguments',
'isElement', 'isError', 'isFunction', 'isNaN', 'isNull', 'isNumber',
'isPlainObject', 'isRegExp', 'isString', 'isTypedArray', 'isUndefined', 'isEmpty', 'isObject']
this.each(isMethods, function (method) {
if (this[method](object)) {
output = method;
return false;
}
}.bind(this));
return output;
}
});
它向lodash添加了一种称为“ identify”的方法,其工作方式如下:
console.log(_.identify('hello friend')); // isString
柱塞: http ://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN
#5楼
有JavaScript相当于Java的
class.getName()
吗?
不行
ES2015更新 : class Foo {}
的名称为Foo.name
。 名称thing
的类,不管thing
的类型,是thing.constructor.name
。 ES2015环境中的内置构造函数具有正确的name
属性; 例如(2).constructor.name
是"Number"
。
但是,这里有各种各样的骇客,它们都以一种或另一种方式下降:
这是一种可以满足您需要的技巧-请注意,它会修改Object的原型,而人们对此并不满意(通常是出于充分的理由)
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() {
}
};
通过new Thingy
构造的Objects
将具有指向Object
而不是Thingy
的constructor
属性。 因此,我们一开始就陷入困境; 您根本无法信任您无法控制的代码库中的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
对象(例如iframe或弹出窗口)的对象的类型时,使用.constructor
进行类型检查会中断。 这是因为每个“窗口”中每个核心类型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
为了使instanceof
正常工作,这些文字需要包装在一个Object
中,例如
new Number(3) instanceof Number // true
.constructor
检查适用于文字,因为.
方法调用隐式地将文字包装在它们各自的对象类型中
3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true
为什么两个点为3? 因为Javascript将第一个点解释为小数点;)
无法跨框架和跨窗口工作
出于与constructor
属性检查相同的原因, instanceof
也无法在不同的窗口中运行。
使用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 = /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);
}
删除残留物并获取类型名称
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
在哪里有用很重要,但是我目前不认为它与本次讨论非常相关。 我的想法是开放的。 :)
#6楼
您可以使用instanceof
运算符查看对象是否是另一个对象的实例,但是由于没有类,因此无法获得类名。
#7楼
杰森邦廷(Jason Bunting)的答案给了我足够的线索来找到我需要的东西:
<<Object instance>>.constructor.name
因此,例如,在下面的代码中:
function MyObject() {}
var myInstance = new MyObject();
myInstance.constructor.name
将返回"MyObject"
。
#8楼
您可以获得的最接近的类型是typeof
,但是对于任何类型的自定义类型,它仅返回“对象”。 对于这些,请参阅Jason Bunting 。
编辑,Jason由于某种原因删除了他的帖子,因此只需使用Object的constructor
属性即可。
#9楼
您可以使用“ instanceof”运算符来确定对象是否是某个类的实例。 如果您不知道对象类型的名称,则可以使用其构造函数属性。 对象的构造函数属性是对用于初始化它们的函数的引用。 例:
function Circle (x,y,radius) {
this._x = x;
this._y = y;
this._radius = raduius;
}
var c1 = new Circle(10,20,5);
现在,c1.constructor是对Circle()
函数的引用。 您也可以使用typeof
运算符,但是typeof
运算符显示的信息有限。 一种解决方案是使用Object全局对象的toString()
方法。 例如,如果您有一个对象,例如myObject,则可以使用全局Object的toString()
方法来确定myObject类的类型。 用这个:
Object.prototype.toString.apply(myObject);
#10楼
好的,伙计们,多年来,我一直在为此逐步建立一种全面的方法,哈哈! 诀窍是:
- 有创建类的机制。
- 有一种机制可以检查由本机构造函数创建/生成的所有用户创建的类,原语和值。
- 具有将用户创建的类扩展为新类的机制,以使上述功能贯穿您的代码/应用程序/库/等。
例如(或者看我如何处理该问题),请查看以下github上的代码: https : //github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js并搜索:
classOf =
, classOfIs =
和或defineSubClass =
(不带反引号(`))。
如您所见,我有一些机制可以强制classOf
始终为我提供类/构造函数的类型名称,而不管它是原始类型,用户定义的类,使用本机构造函数创建的值,Null,NaN等。对于每个单独的javascript值,我将从classOf
函数获取其唯一类型名称。 另外,除了可以传递值的类型名称之外,我还可以将实际的构造函数传递给sjl.classOfIs
来检查值的类型! 因此,例如:
```//请原谅长名称空间! 我不知道影响,直到使用了一段时间(他们都吮吸哈哈)
var SomeCustomClass = sjl.package.stdlib.Extendable.extend({
constructor: function SomeCustomClass () {},
// ...
}),
HelloIterator = sjl.ns.stdlib.Iterator.extend(
function HelloIterator () {},
{ /* ... methods here ... */ },
{ /* ... static props/methods here ... */ }
),
helloIt = new HelloIterator();
sjl.classOfIs(new SomeCustomClass(), SomeCustomClass) === true; // `true`
sjl.classOfIs(helloIt, HelloIterator) === true; // `true`
var someString = 'helloworld';
sjl.classOfIs(someString, String) === true; // `true`
sjl.classOfIs(99, Number) === true; // true
sjl.classOf(NaN) === 'NaN'; // true
sjl.classOf(new Map()) === 'Map';
sjl.classOf(new Set()) === 'Set';
sjl.classOfIs([1, 2, 4], Array) === true; // `true`
// etc..
// Also optionally the type you want to check against could be the type's name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!
```
如果您有兴趣阅读有关我如何使用上述设置的更多信息,请查看存储库: https : //github.com/elycruz/sjljs
另外还包含有关该主题的内容的书:-Stoyan Stefanov撰写的“ JavaScript模式”。 -《 Javascript-权威指南》。 大卫·弗拉纳根(David Flanagan)。 -和许多其他..(在le le Web上搜索)。
您也可以快速测试我谈论这里的特点: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (也是在URL中的0.5.18路径具有从GitHub源在那儿减去node_modules等。
编码愉快!
#11楼
这是基于接受的答案的实现 :
/** * Returns the name of an object's type. * * If the input is undefined, returns "Undefined". * If the input is null, returns "Null". * If the input is a boolean, returns "Boolean". * If the input is a number, returns "Number". * If the input is a string, returns "String". * If the input is a named function or a class constructor, returns "Function". * If the input is an anonymous function, returns "AnonymousFunction". * If the input is an arrow function, returns "ArrowFunction". * If the input is a class instance, returns "Object". * * @param {Object} object an object * @return {String} the name of the object's class * @see <a href="https://stackoverflow.com/a/332429/14731">https://stackoverflow.com/a/332429/14731</a> * @see getFunctionName * @see getObjectClass */ function getTypeName(object) { const objectToString = Object.prototype.toString.call(object).slice(8, -1); if (objectToString === "Function") { const instanceToString = object.toString(); if (instanceToString.indexOf(" => ") != -1) return "ArrowFunction"; const getFunctionName = /^function ([^(]+)\\(/; const match = instanceToString.match(getFunctionName); if (match === null) return "AnonymousFunction"; return "Function"; } // Built-in types (eg String) or class instances return objectToString; }; /** * Returns the name of a function. * * If the input is an anonymous function, returns "". * If the input is an arrow function, returns "=>". * * @param {Function} fn a function * @return {String} the name of the function * @throws {TypeError} if {@code fn} is not a function * @see getTypeName */ function getFunctionName(fn) { try { const instanceToString = fn.toString(); if (instanceToString.indexOf(" => ") != -1) return "=>"; const getFunctionName = /^function ([^(]+)\\(/; const match = instanceToString.match(getFunctionName); if (match === null) { const objectToString = Object.prototype.toString.call(fn).slice(8, -1); if (objectToString === "Function") return ""; throw TypeError("object must be a Function.\\n" + "Actual: " + getTypeName(fn)); } return match[1]; } catch (e) { throw TypeError("object must be a Function.\\n" + "Actual: " + getTypeName(fn)); } }; /** * @param {Object} object an object * @return {String} the name of the object's class * @throws {TypeError} if {@code object} is not an Object * @see getTypeName */ function getObjectClass(object) { const getFunctionName = /^function ([^(]+)\\(/; const result = object.constructor.toString().match(getFunctionName)[1]; if (result === "Function") { throw TypeError("object must be an Object.\\n" + "Actual: " + getTypeName(object)); } return result; }; function UserFunction() { } function UserClass() { } let anonymousFunction = function() { }; let arrowFunction = i => i + 1; console.log("getTypeName(undefined): " + getTypeName(undefined)); console.log("getTypeName(null): " + getTypeName(null)); console.log("getTypeName(true): " + getTypeName(true)); console.log("getTypeName(5): " + getTypeName(5)); console.log("getTypeName(\\"text\\"): " + getTypeName("text")); console.log("getTypeName(userFunction): " + getTypeName(UserFunction)); console.log("getFunctionName(userFunction): " + getFunctionName(UserFunction)); console.log("getTypeName(anonymousFunction): " + getTypeName(anonymousFunction)); console.log("getFunctionName(anonymousFunction): " + getFunctionName(anonymousFunction)); console.log("getTypeName(arrowFunction): " + getTypeName(arrowFunction)); console.log("getFunctionName(arrowFunction): " + getFunctionName(arrowFunction)); //console.log("getFunctionName(userClass): " + getFunctionName(new UserClass())); console.log("getTypeName(userClass): " + getTypeName(new UserClass())); console.log("getObjectClass(userClass): " + getObjectClass(new UserClass())); //console.log("getObjectClass(userFunction): " + getObjectClass(UserFunction)); //console.log("getObjectClass(userFunction): " + getObjectClass(anonymousFunction)); //console.log("getObjectClass(arrowFunction): " + getObjectClass(arrowFunction)); console.log("getTypeName(nativeObject): " + getTypeName(navigator.mediaDevices.getUserMedia)); console.log("getFunctionName(nativeObject): " + getFunctionName(navigator.mediaDevices.getUserMedia));
我们只有在别无选择时才使用构造函数属性。
#12楼
假设您有var obj;
如果只需要obj类型的名称,例如“ Object”,“ Array”或“ String”,则可以使用以下方法:
Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');
#13楼
您应该像这样使用somevar.constructor.name
:
const getVariableType = a => a.constructor.name.toLowerCase(); const d = new Date(); const res1 = getVariableType(d); // 'date' const num = 5; const res2 = getVariableType(num); // 'number' const fn = () => {}; const res3 = getVariableType(fn); // 'function' console.log(res1); // 'date' console.log(res2); // 'number' console.log(res3); // 'function'
#14楼
使用class.name
。 这也适用于function.name
。
class TestA {}
console.log(TestA.name); // "TestA"
function TestB() {}
console.log(TestB.name); // "TestB"
#15楼
我使用的一些小技巧:
function Square(){
this.className = "Square";
this.corners = 4;
}
var MySquare = new Square();
console.log(MySquare.className); // "Square"
#16楼
如果可以的话,使用constructor.name
函数名。当我不能的时候,使用正则表达式函数。
Function.prototype.getName = function(){
if (typeof this.name != 'undefined')
return this.name;
else
return /function (.+)\(/.exec(this.toString())[1];
};
#17楼
更新资料
确切地说,我认为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"
注意:以下示例已弃用。
Christian Sciberras链接的博客文章中有一个很好的例子。 即,通过扩展对象原型:
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
#18楼
这是我想出的解决方案,它解决了instanceof的缺点。 它可以从跨窗口和跨框架检查对象的类型,并且基本类型没有问题。
function getType(o) {
return Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/)[1];
}
function isInstance(obj, type) {
var ret = false,
isTypeAString = getType(type) == "String",
functionConstructor, i, l, typeArray, context;
if (!isTypeAString && getType(type) != "Function") {
throw new TypeError("type argument must be a string or function");
}
if (obj !== undefined && obj !== null && obj.constructor) {
//get the Function constructor
functionConstructor = obj.constructor;
while (functionConstructor != functionConstructor.constructor) {
functionConstructor = functionConstructor.constructor;
}
//get the object's window
context = functionConstructor == Function ? self : functionConstructor("return window")();
//get the constructor for the type
if (isTypeAString) {
//type is a string so we'll build the context (window.Array or window.some.Type)
for (typeArray = type.split("."), i = 0, l = typeArray.length; i < l && context; i++) {
context = context[typeArray[i]];
}
} else {
//type is a function so execute the function passing in the object's window
//the return should be a constructor
context = type(context);
}
//check if the object is an instance of the constructor
if (context) {
ret = obj instanceof context;
if (!ret && (type == "Number" || type == "String" || type == "Boolean")) {
ret = obj.constructor == context
}
}
}
return ret;
}
isInstance需要两个参数:一个对象和一个类型。 真正的工作方式是检查对象是否来自同一窗口,如果不是,则获取对象的窗口。
例子:
isInstance([], "Array"); //true
isInstance("some string", "String"); //true
isInstance(new Object(), "Object"); //true
function Animal() {}
function Dog() {}
Dog.prototype = new Animal();
isInstance(new Dog(), "Dog"); //true
isInstance(new Dog(), "Animal"); //true
isInstance(new Dog(), "Object"); //true
isInstance(new Animal(), "Dog"); //false
type参数也可以是返回构造函数的回调函数。 回调函数将接收一个参数,该参数是所提供对象的窗口。
例子:
//"Arguments" type check
var args = (function() {
return arguments;
}());
isInstance(args, function(w) {
return w.Function("return arguments.constructor")();
}); //true
//"NodeList" type check
var nl = document.getElementsByTagName("*");
isInstance(nl, function(w) {
return w.document.getElementsByTagName("bs").constructor;
}); //true
要记住的一件事是IE <9并未在所有对象上提供构造函数,因此上述对NodeList的测试将返回false,而isInstance(alert,“ Function”)还将返回false。
#19楼
使用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