是否有Java的JavaScript等价物class.getName()
?
是否有Java的JavaScript等价物
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() { } };
Objects
通过构建new 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或弹出式窗口.这是因为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
财产检查相同的原因,也不会在不同的窗口工作.
name
酒店的constructor
财产......再次,见上文; constructor
完全错误和无用是很常见的.
使用myObjectInstance.constructor.name
将给你一个包含所用constructor
函数名称的字符串,但是受到constructor
前面提到的属性的警告.
对于IE9及更高版本,您可以支持Monkey-patch:
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
- 低级别和通用实现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的回答给了我足够的线索来找到我需要的东西:
<
因此,例如,在下面的代码中:
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
这是我提出的一个解决方案,它解决了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.
我实际上是在寻找类似的东西并遇到了这个问题.以下是我如何获得类型: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); }
尽可能使用constructor.name
,当我不能使用时使用正则表达式.
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对象和基元,无论它们是如何创建的,并且没有任何意外.例子:
kind(37) === 'Number' kind(3.14) === 'Number' kind(Math.LN2) === 'Number' kind(Infinity) === 'Number' kind(Number(1)) === 'Number' kind(new Number(1)) === 'Number'
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'
您可以使用instanceof
运算符来查看对象是否是另一个对象的实例,但由于没有类,因此无法获取类名.