Jas*_*ing 1512
是否有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] : "";
};
Run Code Online (Sandbox Code Playgroud)
现在,所有对象都将具有该函数,该函数getName()将构造函数的名称作为字符串返回.我在测试这FF3和IE7,我不能代表其他实现说话.
如果你不想这样做,这里讨论一下在JavaScript中确定类型的各种方法......
我最近更新了这个更详尽一点,尽管不是那样.更正欢迎......
constructor财产......每个object都有它的constructor属性值,但是根据它的object构造方式以及你想用这个值做什么,它可能有用也可能没用.
一般来说,您可以使用该constructor属性来测试对象的类型,如下所示:
var myArray = [1,2,3];
(myArray.constructor == Array); // true
Run Code Online (Sandbox Code Playgroud)
因此,这对大多数需求都足够好.那说......
在许多情况下无法全部工作
这种模式虽然破碎,却很常见:
function Thingy() {
}
Thingy.prototype = {
method1: function() {
},
method2: function() {
}
};
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
事情现在不像你期望的那样有效:
var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true
Run Code Online (Sandbox Code Playgroud)
因此,如果object您的测试具有不同的object设置,则可能会得到意外的结果prototype.在本讨论的范围之外,有很多方法可以解决这个问题.
该constructor物业还有其他用途,其中一些是有趣的,另一些则不是很多; 目前我们不会深入研究这些用途,因为它与此讨论无关.
不会跨框架和跨窗口工作
使用.constructor进行类型检查时要检查从不同的未来对象的类型将打破window对象,说的iframe或弹出式窗口.这是因为constructor每个"窗口"中的每个核心类型都有不同的版本,即
iframe.contentWindow.Array === Array // false
Run Code Online (Sandbox Code Playgroud)
instanceof运营商......该instanceof运营商正在测试的一个干净的方式object式为好,但有自己潜在的问题,就像constructor财产.
var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true
Run Code Online (Sandbox Code Playgroud)
但是instanceof没有为字面值工作(因为文字不是Objects)
3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false
Run Code Online (Sandbox Code Playgroud)
例如,文字需要包含在一个Object以便instanceof工作
new Number(3) instanceof Number // true
Run Code Online (Sandbox Code Playgroud)
该.constructor检查适用于文字,因为.方法调用隐式地将文字包装在它们各自的对象类型中
3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true
Run Code Online (Sandbox Code Playgroud)
为什么两个点为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) {}
});
}
Run Code Online (Sandbox Code Playgroud)
来自相关文章的更新版本.这是在文章发表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) {}
});
}
Run Code Online (Sandbox Code Playgroud)
事实证明,正如这篇帖子的详细信息,您可以使用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]
Run Code Online (Sandbox Code Playgroud)
人们可以写一个简短的辅助函数,如
function type(obj){
return Object.prototype.toString.call(obj).slice(8, -1);
}
Run Code Online (Sandbox Code Playgroud)
删除cruft并获取类型名称
type('abc') // String
Run Code Online (Sandbox Code Playgroud)
但是,它将返回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
Run Code Online (Sandbox Code Playgroud)
虽然并非所有的排列都出现在这组例子中,但希望有足够的信息可以让您了解根据您的需求可能会有多乱.不要假设任何事情,如果你不完全理解你所追求的是什么,你最终可能会因为缺乏细微之处而在你不期望的地方打破代码.
对typeof运算符的讨论似乎是一个明显的遗漏,但它确实无助于确定a是否object是给定类型,因为它非常简单.了解哪里typeof有用很重要,但我目前不认为它与这个讨论非常相关.我的思想可以改变.:)
Ewe*_*ght 119
Jason Bunting的回答给了我足够的线索来找到我需要的东西:
<<Object instance>>.constructor.name
Run Code Online (Sandbox Code Playgroud)
因此,例如,在下面的代码中:
function MyObject() {}
var myInstance = new MyObject();
Run Code Online (Sandbox Code Playgroud)
myInstance.constructor.name会回来的"MyObject".
Dan*_*abo 25
我用的一个小技巧:
function Square(){
this.className = "Square";
this.corners = 4;
}
var MySquare = new Square();
console.log(MySquare.className); // "Square"
Run Code Online (Sandbox Code Playgroud)
Sau*_*aul 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"
Run Code Online (Sandbox Code Playgroud)
注意:以下示例已弃用.
一个博客帖子的链接基督教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
Run Code Online (Sandbox Code Playgroud)
Gau*_*nan 12
使用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]
Run Code Online (Sandbox Code Playgroud)
人们可以写一个简短的辅助函数,如
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
Run Code Online (Sandbox Code Playgroud)
这是我提出的一个解决方案,它解决了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;
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
要记住的一件事是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);
}
Run Code Online (Sandbox Code Playgroud)
小智 8
你应该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'Run Code Online (Sandbox Code Playgroud)
这是基于已接受答案的实现:
/**
* Describes the type of a variable.
*/
class VariableType
{
type;
name;
/**
* Creates a new VariableType.
*
* @param {"undefined" | "null" | "boolean" | "number" | "bigint" | "array" | "string" | "symbol" |
* "function" | "class" | "object"} type the name of the type
* @param {null | string} [name = null] the name of the type (the function or class name)
* @throws {RangeError} if neither <code>type</code> or <code>name</code> are set. If <code>type</code>
* does not have a name (e.g. "number" or "array") but <code>name</code> is set.
*/
constructor(type, name = null)
{
switch (type)
{
case "undefined":
case "null":
case "boolean" :
case "number" :
case "bigint":
case "array":
case "string":
case "symbol":
if (name !== null)
throw new RangeError(type + " may not have a name");
}
this.type = type;
this.name = name;
}
/**
* @return {string} the string representation of this object
*/
toString()
{
let result;
switch (this.type)
{
case "function":
case "class":
{
result = "a ";
break;
}
case "object":
{
result = "an ";
break;
}
default:
return this.type;
}
result += this.type;
if (this.name !== null)
result += " named " + this.name;
return result;
}
}
const functionNamePattern = /^function\s+([^(]+)?\(/;
const classNamePattern = /^class(\s+[^{]+)?{/;
/**
* Returns the type information of a value.
*
* <ul>
* <li>If the input is undefined, returns <code>(type="undefined", name=null)</code>.</li>
* <li>If the input is null, returns <code>(type="null", name=null)</code>.</li>
* <li>If the input is a primitive boolean, returns <code>(type="boolean", name=null)</code>.</li>
* <li>If the input is a primitive number, returns <code>(type="number", name=null)</code>.</li>
* <li>If the input is a primitive or wrapper bigint, returns
* <code>(type="bigint", name=null)</code>.</li>
* <li>If the input is an array, returns <code>(type="array", name=null)</code>.</li>
* <li>If the input is a primitive string, returns <code>(type="string", name=null)</code>.</li>
* <li>If the input is a primitive symbol, returns <code>(type="symbol", null)</code>.</li>
* <li>If the input is a function, returns <code>(type="function", name=the function name)</code>. If the
* input is an arrow or anonymous function, its name is <code>null</code>.</li>
* <li>If the input is a function, returns <code>(type="function", name=the function name)</code>.</li>
* <li>If the input is a class, returns <code>(type="class", name=the name of the class)</code>.
* <li>If the input is an object, returns
* <code>(type="object", name=the name of the object's class)</code>.
* </li>
* </ul>
*
* Please note that built-in types (such as <code>Object</code>, <code>String</code> or <code>Number</code>)
* may return type <code>function</code> instead of <code>class</code>.
*
* @param {object} value a value
* @return {VariableType} <code>value</code>'s type
* @see <a href="http://stackoverflow.com/a/332429/14731">http://stackoverflow.com/a/332429/14731</a>
* @see isPrimitive
*/
function getTypeInfo(value)
{
if (value === null)
return new VariableType("null");
const typeOfValue = typeof (value);
const isPrimitive = typeOfValue !== "function" && typeOfValue !== "object";
if (isPrimitive)
return new VariableType(typeOfValue);
const objectToString = Object.prototype.toString.call(value).slice(8, -1);
// eslint-disable-next-line @typescript-eslint/ban-types
const valueToString = value.toString();
if (objectToString === "Function")
{
// A function or a constructor
const indexOfArrow = valueToString.indexOf("=>");
const indexOfBody = valueToString.indexOf("{");
if (indexOfArrow !== -1 && (indexOfBody === -1 || indexOfArrow < indexOfBody))
{
// Arrow function
return new VariableType("function");
}
// Anonymous and named functions
const functionName = functionNamePattern.exec(valueToString);
if (functionName !== null && typeof (functionName[1]) !== "undefined")
{
// Found a named function or class constructor
return new VariableType("function", functionName[1].trim());
}
const className = classNamePattern.exec(valueToString);
if (className !== null && typeof (className[1]) !== "undefined")
{
// When running under ES6+
return new VariableType("class", className[1].trim());
}
// Anonymous function
return new VariableType("function");
}
if (objectToString === "Array")
return new VariableType("array");
const classInfo = getTypeInfo(value.constructor);
return new VariableType("object", classInfo.name);
}
function UserFunction()
{
}
function UserClass()
{
}
let anonymousFunction = function()
{
};
let arrowFunction = i => i + 1;
console.log("getTypeInfo(undefined): " + getTypeInfo(undefined));
console.log("getTypeInfo(null): " + getTypeInfo(null));
console.log("getTypeInfo(true): " + getTypeInfo(true));
console.log("getTypeInfo(5): " + getTypeInfo(5));
console.log("getTypeInfo(\"text\"): " + getTypeInfo("text"));
console.log("getTypeInfo(userFunction): " + getTypeInfo(UserFunction));
console.log("getTypeInfo(anonymousFunction): " + getTypeInfo(anonymousFunction));
console.log("getTypeInfo(arrowFunction): " + getTypeInfo(arrowFunction));
console.log("getTypeInfo(userObject): " + getTypeInfo(new UserClass()));
console.log("getTypeInfo(nativeObject): " + getTypeInfo(navigator.mediaDevices.getUserMedia));Run Code Online (Sandbox Code Playgroud)
当我们别无选择时,我们只使用构造函数属性。
尽可能使用constructor.name,当我不能使用时使用正则表达式.
Function.prototype.getName = function(){
if (typeof this.name != 'undefined')
return this.name;
else
return /function (.+)\(/.exec(this.toString())[1];
};
Run Code Online (Sandbox Code Playgroud)
Agave.JS的kind()函数将返回:
它适用于所有JS对象和基元,无论它们是如何创建的,并且没有任何意外.例子:
kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'
Run Code Online (Sandbox Code Playgroud)
kind(NaN) === 'NaN'
Run Code Online (Sandbox Code Playgroud)
kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'
Run Code Online (Sandbox Code Playgroud)
kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'
Run Code Online (Sandbox Code Playgroud)
kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'
Run Code Online (Sandbox Code Playgroud)
kind({a:1}) === 'Object'
kind(new Object()) === 'Object'
Run Code Online (Sandbox Code Playgroud)
kind(new Date()) === 'Date'
Run Code Online (Sandbox Code Playgroud)
kind(function(){}) === 'Function'
kind(new Function("console.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'
Run Code Online (Sandbox Code Playgroud)
kind(undefined) === 'undefined'
Run Code Online (Sandbox Code Playgroud)
kind(null) === 'null'
Run Code Online (Sandbox Code Playgroud)
您可以使用instanceof运算符来查看对象是否是另一个对象的实例,但由于没有类,因此无法获取类名.
| 归档时间: |
|
| 查看次数: |
721122 次 |
| 最近记录: |