如何获得一个JavaScript对象的类?
我创build了一个JavaScript对象,但我如何确定该对象的类?
我想要类似于Java的.getClass()
方法。
JavaScript中没有与Java的getClass()
完全相同的对象。 这主要是由于JavaScript是基于原型的语言 ,而Java是基于类的 。
根据你所需要的getClass()
,JavaScript中有几个选项:
-
typeof
-
instanceof
-
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
在现代浏览器的大多数情况下,尽pipeFunction.name
没有正式添加到标准,直到ES6。 如果对象用var obj = new MyClass()
实例化,它将以stringforms返回“MyClass”。
它会返回数字“数字”,数组返回“数组”和函数返回的“函数”等。这似乎是相当可靠的。 唯一失败的情况是如果通过Object.create( null )
创build的对象没有原型,或者该对象是从匿名定义(未命名)函数实例化的。
可以说, obj.constructor.name
比typeof
更直观,可以封装在一个函数中,以处理constructor
未定义(以及处理空引用)的奇怪情况。
注意:这个方法的另一个好处是它直接在DOM边界上工作,而不用直接比较构造函数对象或使用instanceOf
。 不能像你所期望的那样工作的原因是每个DOM上的构造函数实际上有不同的实例,因此在构造函数上做一个对象比较是行不通的。
注2:奇怪的是,这个方法似乎返回了原型链中使用的最基本函数的名字,这不幸并不直观。 例如,如果B
从A
派生出原型,并且创build了B
的新实例B
,则b.constructor.name
返回“A”! 所以感觉完全倒退。 但是,它对单级原型和所有基元都能正常工作。
该函数从Object.prototype.toString.call(someObject)
[object class]
"undefined"
, "null"
或"class"
。
function getClass(obj) { if (typeof obj === "undefined") return "undefined"; if (obj === null) return "null"; return Object.prototype.toString.call(obj) .match(/^\[object\s(.*)\]$/)[1]; } getClass("") === "String"; getClass(true) === "Boolean"; getClass(0) === "Number"; getClass([]) === "Array"; getClass({}) === "Object"; getClass(null) === "null"; // etc...
要获得“伪类”,可以通过获取构造函数
obj.constructor
假设constructor
在你inheritance的时候被正确地设置了 – 就像这样:
Dog.prototype = new Animal(); Dog.prototype.constructor = Dog;
这两条线连同:
var woofie = new Dog()
将使woofie.constructor
指向Dog
。 请注意, Dog
是一个构造函数,并且是一个Function
对象。 但是,你可以做if (woofie.constructor === Dog) { ... }
。
如果你想获得类名作为string,我发现以下工作:
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; }
它获取到构造函数,将其转换为string,并提取构造函数的名称。
请注意, obj.constructor.name
可以运行良好,但不是标准的。 它在Chrome和Firefox上,但不在IE上,包括IE 9或IE 10 RTM。
您可以通过使用构造函数属性来获取对创build对象的构造函数的引用:
function MyObject(){ } var obj = new MyObject(); obj.constructor; // MyObject
如果您需要在运行时确认对象的types,则可以使用instanceof运算符:
obj instanceof MyObject // true
我发现在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; };
对于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()
会告诉你你需要什么。
同意dfa,这就是为什么我认为prototye作为没有命名的类find类
这是Eli Gray发布的升级function,以配合我的思维方式
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; }
下面是getClass()
和getInstance()
您可以使用window
获取对象的类的引用。
从实例上下文:
function A() { this.getClass = function() { return window[this.constructor.name]; } this.getNewInstance = function() { return new window[this.constructor.name]; } } var a = new A(); console.log(a.getClass()); // function A { // etc... } // you can even: var b = new a.getClass(); b instanceof A; // true
从静态上下文:
function B() {}; B.getClass = function() { return window[this.name]; } B.getInstance() { return new window[this.name]; }
我现在有一个工作通用的情况,并使用它:
class Test { // your class definition } nameByType = function(type){ return type.prototype["constructor"]["name"]; }; console.log(nameByType(Test));
这是唯一的方法,我发现通过typesinput获取类名,如果你没有一个对象的实例。
(写在ES2017)
点符号也工作正常
console.log(Test.prototype.constructor.name); // returns "Test"
Javascript是一个没有类的语言:没有类像Java一样静态地定义一个类的行为。 JavaScript使用原型而不是类来定义对象属性,包括方法和inheritance。 有可能在JavaScript中用原型来模拟许多基于类的特性。
为了保持向后兼容性的ECMAScript 6,JavaScript仍然没有class
types(尽pipe不是每个人都明白这一点)。 它有一个class
关键字作为创build原型的class
语法的一部分 – 但仍然没有任何东西叫做class 。 JavaScript不是现在, 从来没有经典的OOP语言 。 谈到JS的类,只是误导或标志尚未grookking原型inheritance(只是保持真实)。
这意味着this.constructor
仍然是获取对constructor
函数的引用的好方法。 而this.constructor.prototype
是访问原型本身的方式。 由于这不是Java,所以不是一个类。 这是你的实例实例化的原型对象。 下面是一个使用ES6语法糖创build原型链的例子:
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
关键字,但仍然没有类的types。 this.constructor
是获得构造函数的最好方法, this.constructor.prototype
是访问原型本身的最好方法。
问题似乎已经回答了,但是OP想要访问类和对象,就像我们在Java中所做的一样,所选的答案是不够的(imho)。
通过下面的解释,我们可以得到一个对象的类(它实际上被称为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
'variables属于哪个对象types(原型)! 换句话说,如果您不知道“ arr
”对象的types(原型),那么您将无法为它们定义属性。 在上面的例子中,我们知道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
'的类。
我们访问了' arr
'的原型而不知道它是Array的一个实例,我想这就是OP所要求的。