Как получить класс объекта JavaScript? - PullRequest
606 голосов
/ 08 августа 2009

Я создал объект JavaScript, но как я могу определить класс этого объекта?

Я хочу что-то похожее на метод Java .getClass().

Ответы [ 15 ]

854 голосов
/ 08 августа 2009

Нет точного аналога Java getClass() в JavaScript. В основном это связано с тем, что JavaScript является основанным на прототипах языком , в отличие от Java, являющимся основанным на классах единым.

В зависимости от того, для чего вам нужен getClass(), в 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, используя gulp или grunt .

247 голосов
/ 03 января 2012
obj.constructor.name

- надежный метод в современных браузерах. Function.name был официально добавлен к стандарту в ES6, что делает его совместимым со стандартами средством получения «класса» объекта JavaScript в виде строки. Если объект создан с var obj = new MyClass(), он вернет «MyClass».

Возвращает «Число» для чисел, «Массив» для массивов и «Функция» для функций и т. Д. Обычно оно работает так, как ожидается. Единственные случаи, когда он терпит неудачу, это если объект создается без прототипа, через Object.create( null ), или объект был создан из анонимно определенной (неназванной) функции.

Также обратите внимание, что если вы минимизируете свой код, сравнивать строки с жестко запрограммированным типом небезопасно. Например, вместо проверки obj.constructor.name == "MyType", вместо проверки obj.constructor.name == MyType.name. Или просто сравните сами конструкторы, однако это не сработает через границы DOM, так как в каждом DOM есть разные экземпляры функции конструктора, поэтому сравнение объектов для их конструкторов не будет работать.

Примечание при создании цепочки прототипов

Редактировать: Это, очевидно, спорный вопрос, теперь, когда ES6 имеет лучшую поддержку классов и наследования. Как объясняет adalbertpl, constructor.name ведет себя так, как ожидалось в этом сценарии.

Как ни странно, constructor.name возвращает имя самой базовой функции, используемой в цепочке прототипов, что, к сожалению, не интуитивно понятно. Например, если B является прототипом A и вы создаете новый экземпляр B, b, b.constructor.name возвращает «A», что кажется неправильным. Однако он отлично работает для одноуровневых прототипов и всех примитивов.

27 голосов
/ 09 августа 2009

Эта функция возвращает либо "undefined", "null", либо "class" в [object class] из Object.prototype.toString.call(someObject).

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...
17 голосов
/ 04 октября 2012

Чтобы получить «псевдо-класс», вы можете получить функцию конструктора,

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.

11 голосов
/ 08 августа 2009

Вы можете получить ссылку на функцию конструктора, которая создала объект, используя свойство конструктора :

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

Если вам нужно подтвердить тип объекта во время выполнения, вы можете использовать оператор instanceof :

obj instanceof MyObject // true
4 голосов
/ 29 мая 2017

У меня была ситуация, чтобы работать сейчас общий и использовал это:

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" 
4 голосов
/ 01 августа 2016

В соответствии со своей непрерывной записью обратной совместимости, ECMAScript 6, JavaScript по-прежнему не имеет типа class (хотя не все это понимают). Он имеет ключевое слово class как часть его синтаксиса class для создания прототипов, но все еще не называется классом . JavaScript сейчас не существует и никогда не был классическим языком ООП . Говоря о 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 - лучший способ получить доступ к самому прототипу.

3 голосов
/ 02 февраля 2016

Для классов Javascript в ES6 вы можете использовать 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... );

3 голосов
/ 17 декабря 2012

Я нахожу object.constructor.toString() return [object objectClass] в IE, а не function objectClass () {} возвращено в chome. Итак, я думаю, что код в 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; 
    };
2 голосов
/ 08 августа 2009

В javascript нет классов, но я думаю, что вам нужно имя конструктора и obj.constructor.toString() скажет вам, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...