我创建了一个 JavaScript 对象,但是如何确定该对象的类?
我想要类似于 Java 的 .getClass()
方法的东西。
class
类型。它确实具有用于创建原型的 class
关键字和 class
语法,其中方法可以更轻松地访问 super
。
JavaScript 中没有与 Java 的 getClass()
完全对应的内容。这主要是因为 JavaScript 是 prototype-based language,而 Java 是 class-based。
根据您需要 getClass()
的用途,JavaScript 中有几个选项:
类型
实例
obj.constructor
func.prototype, proto.isPrototypeOf
几个例子:
function Foo() {}
var foo = new Foo();
typeof Foo; // == "function"
typeof foo; // == "object"
foo instanceof Foo; // == true
foo.constructor.name; // == "Foo"
Foo.name // == "Foo"
Foo.prototype.isPrototypeOf(foo); // == true
Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21); // == 42
注意:如果您使用 Uglify 编译代码,它将更改非全局类名。为了防止这种情况,Uglify 有一个 --mangle
参数,您可以设置为 false 使用 gulp 或 grunt。
obj.constructor.name
在现代浏览器中是一种可靠的方法。 Function.name
在 ES6 中被正式添加到标准中,使其成为将 JavaScript 对象的“类”作为字符串获取的符合标准的方法。如果对象是用 var obj = new MyClass()
实例化的,它将返回“MyClass”。
它将返回数字的“Number”,数组的“Array”和函数的“Function”等。它通常按预期运行。唯一失败的情况是,如果通过 Object.create( null )
创建的对象没有原型,或者对象是从匿名定义(未命名)的函数中实例化的。
另请注意,如果您正在缩小代码,则与硬编码类型字符串进行比较是不安全的。例如,不检查 if obj.constructor.name == "MyType"
,而是检查 obj.constructor.name == MyType.name
。或者只是比较构造函数本身,但这不会跨越 DOM 边界,因为每个 DOM 上有不同的构造函数实例,因此对它们的构造函数进行对象比较是行不通的。
Function.name
(还)不是 JavaScript 标准的一部分。目前在 Chrome 和 Firefox 中受支持,但在 IE(10) 中不支持。
Object.create(something).constructor === something.constructor
,这也不完全正确。所以 obj.constructor 对于所有用 Object.create 制作的对象都是不可靠的,不管有没有原型。
constructor.name
。函数名称将任意更改。
constructor.name
在 ES6 中的新类支持下的行为符合预期。
此 getNativeClass() 函数为未定义的值返回 "undefined"
,为 null 返回 "null"
。
对于所有其他值,CLASSNAME
部分是从 [object CLASSNAME]
中提取的,这是使用 Object.prototype.toString.call(value)
的结果。
getAnyClass()
的行为与 getNativeClass() 相同,但也支持自定义构造函数
function getNativeClass(obj) {
if (typeof obj === "undefined") return "undefined";
if (obj === null) return "null";
return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}
function getAnyClass(obj) {
if (typeof obj === "undefined") return "undefined";
if (obj === null) return "null";
return obj.constructor.name;
}
getClass("") === "String";
getClass(true) === "Boolean";
getClass(0) === "Number";
getClass([]) === "Array";
getClass({}) === "Object";
getClass(null) === "null";
getAnyClass(new (function Foo(){})) === "Foo";
getAnyClass(new class Foo{}) === "Foo";
// etc...
"Object"
。
return obj.constructor.name
。这给出了相同的结果,而且还处理非本机对象。
我们可以通过执行 'instance.constructor.name' 来读取类的实例名称,如下例所示:
class Person {
type = "developer";
}
let p = new Person();
p.constructor.name // Person
要获取“伪类”,您可以获取构造函数,通过
obj.constructor
假设在您进行继承时正确设置了 constructor
- 这是通过以下方式:
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
这两行,连同:
var woofie = new Dog()
将使 woofie.constructor
指向 Dog
。请注意,Dog
是一个构造函数,并且是一个 Function
对象。但是你可以做if (woofie.constructor === Dog) { ... }
。
如果您想将类名作为字符串获取,我发现以下内容运行良好:
http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects
function getObjectClass(obj) {
if (obj && obj.constructor && obj.constructor.toString) {
var arr = obj.constructor.toString().match(
/function\s*(\w+)/);
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
}
它获取构造函数,将其转换为字符串,并提取构造函数的名称。
请注意,obj.constructor.name
可能效果很好,但它不是标准的。它在 Chrome 和 Firefox 上,但不在 IE 上,包括 IE 9 或 IE 10 RTM。
您可以使用 constructor property 获取对创建对象的构造函数的引用:
function MyObject(){
}
var obj = new MyObject();
obj.constructor; // MyObject
如果您需要在运行时确认对象的类型,您可以使用 instanceof 运算符:
obj instanceof MyObject // true
我现在有一种情况可以通用并使用它:
class Test {
// your class definition
}
nameByType = function(type){
return type.prototype["constructor"]["name"];
};
console.log(nameByType(Test));
如果您没有对象的实例,那是我发现通过类型输入获取类名的唯一方法。
(用 ES2017 编写)
点符号也可以正常工作
console.log(Test.prototype.constructor.name); // returns "Test"
为了保持其向后兼容的完整记录,ECMAScript 6,JavaScript 仍然没有 class
类型(尽管不是每个人都理解这一点)。它确实有一个 class
关键字作为其用于创建原型的 class
语法的一部分,但 仍然没有所谓的类。 JavaScript 现在不是,并且从来都不是经典的 OOP 语言。从类的角度来谈论 JS 要么是误导,要么是尚未理解原型继承的标志(只是保持真实)。
这意味着 this.constructor
仍然是获取对 constructor
函数的引用的好方法。 this.constructor.prototype
是访问原型本身的方式。因为这不是 Java,所以它不是一个类。它是您的实例被实例化的原型对象。下面是一个使用 ES6 语法糖创建原型链的示例:
class Foo {
get foo () {
console.info(this.constructor, this.constructor.name)
return 'foo'
}
}
class Bar extends Foo {
get foo () {
console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))
return `${super.foo} + bar`
}
}
const bar = new Bar()
console.dir(bar.foo)
这是使用 babel-node
输出的内容:
> $ babel-node ./foo.js ⬡ 6.2.0 [±master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'
你有它! 2016 年,JavaScript 中有一个 class
关键字,但仍然没有类类型。 this.constructor
是获取构造函数的最佳方式,this.constructor.prototype
是获取原型本身的最佳方式。
对于 ES6 中的 Javascript 类,您可以使用 object.constructor
。在 getClass()
方法下面的示例类中,如您所料,返回 ES6 类:
var Cat = class {
meow() {
console.log("meow!");
}
getClass() {
return this.constructor;
}
}
var fluffy = new Cat();
...
var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();
ruffles.meow(); // "meow!"
如果您从 getClass
方法实例化类,请确保将其包装在括号中,例如 ruffles = new ( fluffy.getClass() )( args... );
在 javascript 中,没有类,但我认为您需要构造函数名称,obj.constructor.toString()
会告诉您您需要什么。
.name
。
.name
我在 IE 中发现 object.constructor.toString()
返回 [object objectClass]
,而不是在 chome 中返回 function objectClass () {}
。因此,我认为 http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects 中的代码在 IE 中可能无法正常运行。我将代码修复如下:
代码:
var getObjectClass = function (obj) {
if (obj && obj.constructor && obj.constructor.toString()) {
/*
* for browsers which have name property in the constructor
* of the object,such as chrome
*/
if(obj.constructor.name) {
return obj.constructor.name;
}
var str = obj.constructor.toString();
/*
* executed if the return of object.constructor.toString() is
* "[object objectClass]"
*/
if(str.charAt(0) == '[')
{
var arr = str.match(/\[\w+\s*(\w+)\]/);
} else {
/*
* executed if the return of object.constructor.toString() is
* "function objectClass () {}"
* for IE Firefox
*/
var arr = str.match(/function\s*(\w+)/);
}
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
};
使用 constructor.prototype.name 的 getClass() 函数
我找到了一种访问 class
的方法,它比上面的一些解决方案更干净;这里是。
function getClass(obj) {
// if the type is not an object return the type
if((let type = typeof obj) !== 'object') return type;
//otherwise, access the class using obj.constructor.name
else return obj.constructor.name;
}
这个怎么运作
构造函数有一个名为 name
的访问属性,它将为您提供类名。
更简洁的代码版本:
function getClass(obj) {
// if the type is not an object return the type
let type = typeof obj
if((type !== 'object')) {
return type;
} else { //otherwise, access the class using obj.constructor.name
return obj.constructor.name;
}
}
如果您不仅需要 GET 类,还需要 EXTEND 从只有一个实例,请编写:
让我们
class A{
constructor(name){
this.name = name
}
};
const a1 = new A('hello a1');
所以要扩展 A 只使用实例:
const a2 = new (Object.getPrototypeOf(a1)).constructor('hello from a2')
// the analog of const a2 = new A()
console.log(a2.name)//'hello from a2'
同意 dfa,这就是为什么我在找不到命名类时将原型视为类的原因
这是 Eli Grey 发布的功能的升级功能,以符合我的想法
function what(obj){
if(typeof(obj)==="undefined")return "undefined";
if(obj===null)return "Null";
var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
if(res==="Object"){
res = obj.constructor.name;
if(typeof(res)!='string' || res.length==0){
if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
if(obj instanceof Array)return "Array";// Array prototype is very sneaky
return "Object";
}
}
return res;
}
我建议使用 Object.prototype.constructor.name
:
Object.defineProperty(Object.prototype, "getClass", {
value: function() {
return this.constructor.name;
}
});
var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'
var y = new Error("");
console.log(y.getClass()); // `Error'
这是 getClass() 和 getInstance() 的实现
您可以使用 this.constructor
获取对象类的引用。
从实例上下文:
function A() {
this.getClass = function() {
return this.constructor;
}
this.getNewInstance = function() {
return new this.constructor;
}
}
var a = new A();
console.log(a.getClass()); // function A { // etc... }
// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true
从静态上下文:
function A() {};
A.getClass = function() {
return this;
}
A.getInstance() {
return new this;
}
this.constructor
?
你也可以做这样的事情
class Hello { constructor(){ } } function isClass (func) { return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func)) } console.log(是类(你好))
这将告诉您输入是否为类
Javascript 是一种无类语言:没有类可以像在 Java 中那样静态定义类的行为。 JavaScript 使用原型而不是类来定义对象属性,包括方法和继承。可以使用 JavaScript 中的原型来模拟许多基于类的功能。
class
类型。它确实具有用于创建原型的 class
关键字和 class
语法,其中方法可以更轻松地访问 super
。
还有另一种技术可以识别您的类您可以在下面的实例中将 ref 存储到您的类。
class MyClass {
static myStaticProperty = 'default';
constructor() {
this.__class__ = new.target;
this.showStaticProperty = function() {
console.log(this.__class__.myStaticProperty);
}
}
}
class MyChildClass extends MyClass {
static myStaticProperty = 'custom';
}
let myClass = new MyClass();
let child = new MyChildClass();
myClass.showStaticProperty(); // default
child.showStaticProperty(); // custom
myClass.__class__ === MyClass; // true
child.__class__ === MyClass; // false
child.__class__ === MyChildClass; // true
问题似乎已经得到解答,但 OP 想要访问类和对象,就像我们在 Java 中所做的那样,并且选择的答案还不够(恕我直言)。
通过下面的解释,我们可以得到一个对象的一个类(在javascript中它实际上被称为原型)。
var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');
您可以添加这样的属性:
Object.defineProperty(arr,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
但 .last
属性仅可用于从 Array 原型实例化的“arr
”对象。因此,为了使 .last
属性可用于从 Array 原型实例化的所有对象,我们必须为 Array 原型定义 .last
属性:
Object.defineProperty(Array.prototype,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
这里的问题是,您必须知道“arr
”和“arr2
”变量属于哪个对象类型(原型)!换句话说,如果您不知道“arr
”对象的类类型(原型),那么您将无法为它们定义属性。在上面的示例中,我们知道 arr 是 Array 对象的实例,这就是我们使用 Array.prototype 为 Array 定义属性的原因。但是,如果我们不知道“arr
”的类(原型)怎么办?
Object.defineProperty(arr.__proto__,'last2', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
如您所见,在不知道“arr
”是一个数组的情况下,我们可以通过使用“arr.__proto__
”添加一个新属性,只需引用“arr
”的类即可。
我们在不知道它是 Array 实例的情况下访问了“arr
”的原型,我认为这就是 OP 所要求的。
__proto__
属性已被弃用,与 prototype
属性相比几乎没有优势。
func.prototype
(是的,函数是对象,但prototype
属性仅与函数对象相关)。instanceof
/isPrototypeOf()
和非标准的__proto__
Object.getPrototypeOf()
constructor.name
。函数名称将任意更改。construction.name
识别为要忽略/不最小化的令牌。此外,大多数(如果不是全部)缩小器软件都提供异常规则。