首页 文章

如何获得JavaScript对象的类?

提问于
浏览
533

我创建了一个JavaScript对象,但是我如何确定该对象的类?

我想要类似于Java的 .getClass() 方法 .

14 回答

  • 3

    JavaScript中有's no exact counterpart to Java' s getClass() . 主要是因为JavaScript是prototype-based language,而Java则是class-based .

    根据您的需要 getClass() for,JavaScript中有几个选项:

    几个例子:

    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使用gulpgrunt .

  • 3
    obj.constructor.name
    

    尽管 Function.name 在ES6之前没有正式添加到标准中,但在大多数情况下在现代浏览器中都有效 . 如果使用 var obj = new MyClass() 实例化对象,它将返回"MyClass"作为字符串 .

    它将返回数字"Number",数组返回"Array",函数返回"Function"等 . 它似乎非常可靠 . 它失败的唯一情况是如果没有原型创建对象,通过 Object.create( null ) ,或者对象是从匿名定义的(未命名)函数实例化的 .

    可以说, obj.constructor.nametypeof 更直观,并且可以封装在一个函数中来处理未定义 constructor 的奇怪情况(以及处理空引用) .

    Note: 此方法的另一个优点是,它可以直观地跨DOM边界工作,而不是直接比较构造函数对象或使用 instanceOf . 之所以不起作用 .

    Note 2: 奇怪的是,这个方法似乎返回了原型链中使用的最基本函数的名称,遗憾的是,这个名称并不直观 . 例如,如果 BA 原型派生,并且您创建 B 的新实例, bb.constructor.name 返回"A"!所以感觉完全倒退 . 然而,它确实适用于单级原型和所有基元 .

  • -1

    此函数从 Object.prototype.toString.call(someObject) 返回 "undefined""null"[object class] 中的 "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...
    
  • 4

    要获得“伪类”,可以通过获取构造函数

    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 .

  • -2

    您可以使用constructor property获取对创建该对象的构造函数的引用:

    function MyObject(){
    }
    
    var obj = new MyObject();
    obj.constructor; // MyObject
    

    如果需要在运行时确认对象的类型,可以使用instanceof运算符:

    obj instanceof MyObject // true
    
  • 220

    为了保持其完整的向后兼容性记录ECMAScript 6,JavaScript仍然没有 class 类型(虽然不是每个人都理解这一点) . 它 doesclass 关键字作为其创建原型的 class 语法的一部分 - 但 still no thing called class . JavaScript现在不是 never been a classical OOP language . 说到JS在类方面只是误导或者还没有表达原型继承(只是保持真实) .

    这意味着 this.constructor 仍然是获取 constructor 函数引用的好方法 . 并且 this.constructor.prototype 是访问原型本身的方式 . 因为这不是一个阶级 . 它是您的实例实例化的原型对象 . 以下是使用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 是访问原型本身的最佳方式 .

  • 4

    我现在有一个工作通用的情况并使用它:

    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"
    
  • 17

    我发现 object.constructor.toString() 在IE中返回 [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; 
        };
    
  • 1

    对于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... );

  • 755

    在javascript中,没有类,但我认为你想要构造函数名称, obj.constructor.toString() 会告诉你你需要什么 .

  • 7

    同意dfa,这就是为什么我认为prototye是没有找到命名类的类

    这是Eli Gray发布的升级功能,以符合我的心态

    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;
    }
    
  • 2

    Javascript是一种无类语言:没有类像Java那样静态地定义类的行为 . JavaScript使用原型而不是类来定义对象属性,包括方法和继承 . 可以使用JavaScript中的原型模拟许多基于类的功能 .

  • 24

    这是getClass()和getInstance()的实现

    您可以使用 window 获取Object类的引用 .

    来自实例上下文:

    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];
    }
    
  • 0

    问题似乎已经得到解答,但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 属性只能用于' arr '对象,该对象是从Array原型实例化的 . 因此,为了使 .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 ' and ' arr2 ' variables belongs to! In other words, if you don'知道类的类型(原型)的' arr ' object, then you won'能够为它们定义属性的对象类型(原型) . 在上面的例子中,我们知道arr是Array对象的实例,'s why we used Array.prototype to define a property for Array. But what if we didn'知道' arr '的类(原型)?

    Object.defineProperty(arr.__proto__,'last2', {
      get: function(){
        return this[this.length -1];
      }
    });
    console.log(arr.last) // blue
    console.log(arr2.last) // orange
    

    如你所见,不知道' arr ' is an Array, we can add a new property just bu referring the class of the ' arr ' by using ' arr.__proto__ ' .

    我们访问了' arr ' without knowing that it'的一个Array实例的原型,我认为这就是OP所要求的 .

相关问题