Get the name of an object's type
是否有一个JavaScript相当于Java的EDCOX1?0?
Is there a JavaScript equivalent of Java's
class.getName() ?Ok.
不。好的。
ES2015更新:
但这里有各种各样的黑客,它们都以某种方式倒下:好的。
这里有一个可以做你需要做的事情的黑客-注意它修改了对象的原型,这是人们不喜欢的事情(通常是有充分理由的)好的。
1 2 3 4 5 | Object.prototype.getName = function() { var funcNameRegex = /function (.{1,})\(/; var results = (funcNameRegex).exec((this).constructor.toString()); return (results && results.length > 1) ? results[1] :""; }; |
现在,所有对象都将具有函数
如果您不想这样做,这里将讨论在javascript中确定类型的各种方法…好的。
我最近把这个更新得更详尽了一点,尽管这很难做到。欢迎更正…好的。使用
每个
一般来说,您可以使用
1 2 | var myArray = [1,2,3]; (myArray.constructor == Array); // true |
所以,这对大多数需求来说已经足够好了。说…好的。告诫
在很多情况下根本不起作用好的。
这种模式虽然已被打破,但很常见:好的。
1 2 3 4 5 6 7 8 | function Thingy() { } Thingy.prototype = { method1: function() { }, method2: function() { } }; |
通过
多重继承好的。
一个不那么明显的例子是使用多重继承:好的。
1 2 3 | function a() { this.foo = 1;} function b() { this.bar = 2; } b.prototype = new a(); // b inherits from a |
现在事情并不像你期望的那样运作:好的。
1 2 3 | var f = new b(); // instantiate a new object with the b constructor (f.constructor == b); // false (f.constructor == a); // true |
因此,如果您的测试将不同的
不能跨框架和跨窗工作好的。
当您想检查来自不同
1 | iframe.contentWindow.Array === Array // false |
使用
1 2 3 | var myArray = [1,2,3]; (myArray instanceof Array); // true (myArray instanceof Object); // true |
但是,
1 2 3 | 3 instanceof Number // false 'abc' instanceof String // false true instanceof Boolean // false |
例如,为了使
1 | new Number(3) instanceof Number // true |
对于文本,
1 2 3 | 3..constructor === Number // true 'abc'.constructor === String // true true.constructor === Boolean // true |
为什么三个点有两个点?因为javascript将第一个点解释为小数点;)好的。不能跨框架和跨窗工作
再说一次,看上面,以东十一〔七〕是完全错误和无用的,这是很常见的。好的。不适用于 对于IE9及以上版本,您可以使用monkey patch来支持:好的。 相关文章的更新版本。这是在文章发表3个月后添加的,这是文章作者MatthewScharley推荐使用的版本。这一变化的灵感来自于前面代码中指出潜在陷阱的注释。好的。 使用object.prototype.toString 事实证明,正如本文详细介绍的那样,您可以使用 可以编写一个简短的助手函数,例如好的。 移除cruft并获取类型名好的。 但是,对于所有用户定义的类型,它将返回 所有这些都受制于一个潜在的问题,那就是有关对象是如何构造的问题。以下是构建对象的各种方法以及不同类型检查方法将返回的值:好的。 虽然并不是所有的排列都出现在这组示例中,但希望有足够的空间让您了解根据您的需要,事情可能会变得多么混乱。不要假设任何事情,如果你不确切地理解你在追求什么,你可能会以代码破坏而告终,因为你缺乏对微妙之处的摸索。好的。注: 对 杰森·邦廷的回答给了我足够的线索来找到我需要的东西:
2
3
4
5
6
7
8
9
10
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) {}
});
}
2
3
4
5
6
7
8
9
10
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) {}
});
}
2
3
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]
2
3
return Object.prototype.toString.call(obj).slice(8, -1);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
1 | <<Object instance>>.constructor.name |
例如,在下面的代码中:
1 2 | function MyObject() {} var myInstance = new MyObject(); |
我使用的一个小技巧:
1 2 3 4 5 6 7 | function Square(){ this.className ="Square"; this.corners = 4; } var MySquare = new Square(); console.log(MySquare.className); //"Square" |
更新
准确地说,我认为op要求一个函数来检索特定对象的构造函数名。就javascript而言,
1 2 3 4 5 6 7 8 9 | 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" |
nbsp;
注意:下面的示例已弃用。
一篇由ChristianSciberras链接的博客文章包含了一个如何做到这一点的好例子。也就是说,通过扩展对象原型:
1 2 3 4 5 6 7 8 9 | 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的低级和通用实现)来获取所有内置类型的类型。
1 2 3 | Object.prototype.toString.call('abc') // [object String] Object.prototype.toString.call(/abc/) // [object RegExp] Object.prototype.toString.call([1,2,3]) // [object Array] |
可以编写一个简短的助手函数,例如
1 2 3 4 5 6 7 8 9 | 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 |
下面是我提出的解决方案,它解决了InstanceOf的缺点。它可以从交叉窗口和交叉框架中检查对象的类型,并且与基本类型没有问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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需要两个参数:一个对象和一个类型。如何工作的真正技巧是,它检查对象是否来自同一个窗口,如果不来自该对象的窗口。
实例:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
类型参数也可以是返回构造函数的回调函数。回调函数将接收一个参数,该参数是所提供对象的窗口。
实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | //"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。
我实际上在找一个类似的东西,遇到了这个问题。以下是我获取类型的方法:jspiddle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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); } |
可以的时候用
1 2 3 4 5 6 | Function.prototype.getName = function(){ if (typeof this.name != 'undefined') return this.name; else return /function (.+)\(/.exec(this.toString())[1]; }; |
agave.js中的kind()函数将返回:
- 继承树中最近的原型
- 对于"null"和"undefined"这样的始终基元类型,基元名称。
它适用于所有JS对象和原语,不管它们是如何创建的,并且没有任何意外。实例:
数字1 2 3 4 5 6 | kind(37) === 'Number' kind(3.14) === 'Number' kind(Math.LN2) === 'Number' kind(Infinity) === 'Number' kind(Number(1)) === 'Number' kind(new Number(1)) === 'Number' |
南
1 | kind(NaN) === 'NaN' |
串
1 2 3 4 | kind('') === 'String' kind('bla') === 'String' kind(String("abc")) === 'String' kind(new String("abc")) === 'String' |
布尔值
1 2 3 | kind(true) === 'Boolean' kind(false) === 'Boolean' kind(new Boolean(true)) === 'Boolean' |
数组
1 2 | kind([1, 2, 4]) === 'Array' kind(new Array(1, 2, 3)) === 'Array' |
物体
1 2 | kind({a:1}) === 'Object' kind(new Object()) === 'Object' |
日期
1 | kind(new Date()) === 'Date' |
功能
1 2 3 | kind(function(){}) === 'Function' kind(new Function("console.log(arguments)")) === 'Function' kind(Math.sin) === 'Function' |
未定义
1 | kind(undefined) === 'undefined' |
无效的
1 | kind(null) === 'null' |
可以使用
以下是基于接受答案的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /** * 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 https://stackoverflow.com/a/332429/14731 * @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 (e.g. 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. " + "Actual:" + getTypeName(fn)); } return match[1]; } catch (e) { throw TypeError("object must be a Function. " + "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. " + "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)); |
我们只有在没有其他选择时才使用构造函数属性。
可以使用"instance of"运算符确定对象是否为某个类的实例。如果不知道对象类型的名称,可以使用其构造函数属性。对象的构造函数属性是对用于初始化它们的函数的引用。例子:
1 2 3 4 5 6 | function Circle (x,y,radius) { this._x = x; this._y = y; this._radius = raduius; } var c1 = new Circle(10,20,5); |
现在,c1.constructor是对
1 | Object.prototype.toString.apply(myObject); |
最接近的是
编辑,杰森出于某种原因删除了他的文章,所以只需使用对象的
您应该像使用:
1 2 3 4 5 6 7 8 9 10 11 12 | 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' |
比如说你有一个
如果只需要对象类型的名称,如"object"、"array"或"string",您可以使用:
1 | Object.prototype.toString.call(obj).split(' ')[1].replace(']', ''); |
如果有人在寻找一个与jquery一起工作的解决方案,这里是调整后的wiki代码(原来的中断jquery)。
24使用
1 2 3 4 5 | class TestA {} console.log(TestA.name); //"TestA" function TestB() {} console.log(TestB.name); //"TestB" |
罗达什有很多种方法,所以如果你使用罗达什,像这样的混合可能会有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // 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中添加了一个名为"识别"的方法,其工作原理如下:
1 | console.log(_.identify('hello friend')); // isString |
Plunker:http://plnkr.co/edit/zdr0kdtqt76ul3ktdsn
好吧,伙计们,多年来我一直在慢慢地建立一个"一网打尽"的方法,哈哈!诀窍是:
例如(或查看我如何处理该问题),请查看GitHub上的以下代码:https://github.com/elycruz/sjl js/blob/master/src/sjl/sjl.js并搜索:
如您所见,我有一些机制可以强制
` `//请原谅长名称空间!我不知道会有什么影响,直到用了一段时间后(他们吸哈哈)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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`! |
` `
如果您有兴趣了解更多关于如何使用上述设置的信息,请访问repo:https://github.com/elycruz/sjljs
还有关于这个主题的书:-Stoyan Stefanov的"javascript模式"。-"javascript-权威指南。"作者:大卫·弗拉纳根。-还有很多其他的……(搜索le`web)。
此外,您还可以快速测试我在这里讨论的功能:-http://sjljs.elycruz.com/0.5.18/tests/for-browser/(此外,URL中的0.5.18路径的源代码是从那里的github减去节点_模块等)。
快乐编码!