Получить название типа объекта - PullRequest
1131 голосов
/ 02 декабря 2008

Есть ли в JavaScript эквивалент Java class.getName()?

Ответы [ 19 ]

3 голосов
/ 04 января 2017

Вот реализация, основанная на принятом ответе :

/**
 * Returns the name of an object's type.
 *
 * If the input is undefined, returns "Undefined".
 * If the input is null, returns "Null".
 * If the input is a boolean, returns "Boolean".
 * If the input is a number, returns "Number".
 * If the input is a string, returns "String".
 * If the input is a named function or a class constructor, returns "Function".
 * If the input is an anonymous function, returns "AnonymousFunction".
 * If the input is an arrow function, returns "ArrowFunction".
 * If the input is a class instance, returns "Object".
 *
 * @param {Object} object an object
 * @return {String} the name of the object's class
 * @see <a href="https://stackoverflow.com/a/332429/14731">https://stackoverflow.com/a/332429/14731</a>
 * @see getFunctionName
 * @see getObjectClass 
 */
function getTypeName(object)
{
  const objectToString = Object.prototype.toString.call(object).slice(8, -1);
  if (objectToString === "Function")
  {
    const instanceToString = object.toString();
    if (instanceToString.indexOf(" => ") != -1)
      return "ArrowFunction";
    const getFunctionName = /^function ([^(]+)\(/;
    const match = instanceToString.match(getFunctionName);
    if (match === null)
      return "AnonymousFunction";
    return "Function";
  }
  // Built-in types (e.g. String) or class instances
  return objectToString;
};

/**
 * Returns the name of a function.
 *
 * If the input is an anonymous function, returns "".
 * If the input is an arrow function, returns "=>".
 *
 * @param {Function} fn a function
 * @return {String} the name of the function
 * @throws {TypeError} if {@code fn} is not a function
 * @see getTypeName
 */
function getFunctionName(fn)
{
  try
  {
    const instanceToString = fn.toString();
    if (instanceToString.indexOf(" => ") != -1)
      return "=>";
    const getFunctionName = /^function ([^(]+)\(/;
    const match = instanceToString.match(getFunctionName);
    if (match === null)
    {
      const objectToString = Object.prototype.toString.call(fn).slice(8, -1);
      if (objectToString === "Function")
        return "";
      throw TypeError("object must be a Function.\n" +
        "Actual: " + getTypeName(fn));
    }
    return match[1];
  }
  catch (e)
  {
    throw TypeError("object must be a Function.\n" +
      "Actual: " + getTypeName(fn));
  }
};

/**
 * @param {Object} object an object
 * @return {String} the name of the object's class
 * @throws {TypeError} if {@code object} is not an Object
 * @see getTypeName
 */
function getObjectClass(object)
{
  const getFunctionName = /^function ([^(]+)\(/;
  const result = object.constructor.toString().match(getFunctionName)[1];
  if (result === "Function")
  {
    throw TypeError("object must be an Object.\n" +
      "Actual: " + getTypeName(object));
  }
  return result;
};


function UserFunction()
{
}

function UserClass()
{
}

let anonymousFunction = function()
{
};

let arrowFunction = i => i + 1;

console.log("getTypeName(undefined): " + getTypeName(undefined));
console.log("getTypeName(null): " + getTypeName(null));
console.log("getTypeName(true): " + getTypeName(true));
console.log("getTypeName(5): " + getTypeName(5));
console.log("getTypeName(\"text\"): " + getTypeName("text"));
console.log("getTypeName(userFunction): " + getTypeName(UserFunction));
console.log("getFunctionName(userFunction): " + getFunctionName(UserFunction));
console.log("getTypeName(anonymousFunction): " + getTypeName(anonymousFunction));
console.log("getFunctionName(anonymousFunction): " + getFunctionName(anonymousFunction));
console.log("getTypeName(arrowFunction): " + getTypeName(arrowFunction));
console.log("getFunctionName(arrowFunction): " + getFunctionName(arrowFunction));
//console.log("getFunctionName(userClass): " + getFunctionName(new UserClass()));
console.log("getTypeName(userClass): " + getTypeName(new UserClass()));
console.log("getObjectClass(userClass): " + getObjectClass(new UserClass()));
//console.log("getObjectClass(userFunction): " + getObjectClass(UserFunction));
//console.log("getObjectClass(userFunction): " + getObjectClass(anonymousFunction));
//console.log("getObjectClass(arrowFunction): " + getObjectClass(arrowFunction));
console.log("getTypeName(nativeObject): " + getTypeName(navigator.mediaDevices.getUserMedia));
console.log("getFunctionName(nativeObject): " + getFunctionName(navigator.mediaDevices.getUserMedia));

Мы используем свойство конструктора, только когда у нас нет другого выбора.

3 голосов
/ 02 декабря 2008

Вы можете использовать оператор instanceof, чтобы определить, является ли объект экземпляром определенного класса или нет. Если вы не знаете имя типа объекта, вы можете использовать его свойство конструктора. Свойство constructor объектов, является ссылкой на функцию, которая используется для их инициализации. Пример:

function Circle (x,y,radius) {
    this._x = x;
    this._y = y;
    this._radius = raduius;
}
var c1 = new Circle(10,20,5);

Теперь c1.constructor является ссылкой на функцию Circle(). Вы также можете использовать оператор typeof, но оператор typeof отображает ограниченную информацию. Одним из решений является использование метода toString() глобального объекта Object. Например, если у вас есть объект, скажем, myObject, вы можете использовать метод toString() глобального объекта Object для определения типа класса myObject. Используйте это:

Object.prototype.toString.apply(myObject);
2 голосов
/ 29 августа 2018

Вы должны использовать 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'
2 голосов
/ 02 декабря 2008

Ближайшее, что вы можете получить, это typeof, но оно возвращает «объект» только для любого пользовательского типа. Для тех, см. Джейсон Бантинг .

Edit, Джейсон почему-то удалил свой пост, поэтому просто используйте свойство Object constructor.

1 голос
/ 02 августа 2017

скажем, у вас есть var obj;

Если вам просто нужно имя типа объекта, например «Объект», «Массив» или «Строка», Вы можете использовать это:

Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');
0 голосов
/ 28 марта 2019

Используйте class.name. Это также работает с function.name.

class TestA {}
console.log(TestA.name); // "TestA"

function TestB() {}
console.log(TestB.name); // "TestB"
0 голосов
/ 19 декабря 2015

Хорошо, ребята, я уже несколько лет медленно разрабатываю метод «поймай все», лол! Хитрость заключается в том, чтобы:

  1. Есть механизм для создания классов.
  2. Иметь механизм для проверки всех пользовательских классов, примитивов и значений, созданных / сгенерированных нативными конструкторами.
  3. Иметь механизм для расширения созданных пользователем классов в новые так, чтобы вышеуказанная функциональность проникала через ваш код / ​​приложение / библиотеку / и т.д ..

Для примера (или посмотреть, как я справился с проблемой), посмотрите следующий код на github: https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js и найдите:

classOf =, classOfIs = и или defineSubClass = (без обратных кавычек (`)).

Как видите, у меня есть некоторые механизмы, чтобы заставить classOf всегда давать мне имя типа class / constructors независимо от того, является ли он примитивом, определяемым пользователем классом, значением, созданным с помощью собственного конструктора, Null , NaN и т. Д. Для каждого значения javascript я получу уникальное имя типа из функции classOf. Кроме того, я могу передать фактические конструкторы в sjl.classOfIs, чтобы проверить тип значения в дополнение к возможности передать его имя типа! Так, например:

`` ` // Пожалуйста, прости длинные пространства имен! Я понятия не имел о воздействии, пока не использовал их некоторое время (они сосут хаха)

var SomeCustomClass = sjl.package.stdlib.Extendable.extend({
    constructor: function SomeCustomClass () {},
    // ...
}),

HelloIterator = sjl.ns.stdlib.Iterator.extend( 
    function HelloIterator () {}, 
    { /* ... methods here ... */ },
    { /* ... static props/methods here ... */ }
),

helloIt = new HelloIterator();

sjl.classOfIs(new SomeCustomClass(), SomeCustomClass) === true; // `true`
sjl.classOfIs(helloIt, HelloIterator) === true; // `true`

var someString = 'helloworld';

sjl.classOfIs(someString, String) === true; // `true`

sjl.classOfIs(99, Number) === true; // true

sjl.classOf(NaN) === 'NaN'; // true

sjl.classOf(new Map()) === 'Map';
sjl.classOf(new Set()) === 'Set';
sjl.classOfIs([1, 2, 4], Array) === true; // `true`

// etc..

// Also optionally the type you want to check against could be the type's name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!

`` `

Если вы хотите узнать больше о том, как я использую вышеупомянутую настройку, взгляните на репозиторий: https://github.com/elycruz/sjljs

Также книги с содержанием по теме: - «Шаблоны JavaScript» Стояна Стефанова. - «Javascript - Полное руководство». Дэвид Фланаган. - и многие другие .. (поиск в сети).

Также вы можете быстро протестировать функции, о которых я говорю, здесь: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (также в пути 0.5.18 в url есть источники из github минус node_modules и тому подобное).

Счастливого кодирования!

0 голосов
/ 24 сентября 2015

В Lodash есть много isMethods, поэтому, если вы используете Lodash, может быть полезен подобный миксин:

  // Mixin for identifying a Javascript Object

  _.mixin({
      'identify' : function(object) {
        var output;
          var isMethods = ['isArguments', 'isArray', 'isArguments', 'isBoolean', 'isDate', 'isArguments', 
              'isElement', 'isError', 'isFunction', 'isNaN', 'isNull', 'isNumber', 
              'isPlainObject', 'isRegExp', 'isString', 'isTypedArray', 'isUndefined', 'isEmpty', 'isObject']

          this.each(isMethods, function (method) {
              if (this[method](object)) {
                output = method;
                return false;
              }
          }.bind(this));
      return output;
      }
  });

Он добавляет в lodash метод, называемый «identifier», который работает следующим образом:

console.log(_.identify('hello friend'));       // isString

Plunker: http://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN

0 голосов
/ 29 июля 2014

Если кто-то искал решение, которое работает с jQuery, вот скорректированный вики-код (оригинал ломает jQuery).

Object.defineProperty(Object.prototype, "getClassName", {
    value: function() {
        var funcNameRegex = /function (.{1,})\(/;
        var results = (funcNameRegex).exec((this).constructor.toString());
        return (results && results.length > 1) ? results[1] : "";
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...