Получить название типа объекта

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

Этот вопрос предполагает, что мы знаем, что делает Java class.getName (). Так как я не знаю, я не уверен, помогут ли мне ответы.

user34660 28.11.2018 05:15

@ user34660 Я думаю, мы можем смело предположить, что он получает имя типа объекта.

Stack Underflow 24.12.2018 19:54

@StackUnderflow: Но на самом деле это не так. Он получает имя класс объекта, которое нет совпадает с тип объекта.

Jörg W Mittag 09.09.2019 17:35

@ JörgWMittag Ах да, конечно. Вы видите, что происходит, когда вы идете безопасно, предполагая что-то?

Stack Underflow 09.09.2019 21:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1 236
4
788 845
20

Ответы 20

Вы можете использовать оператор instanceof, чтобы увидеть, является ли объект экземпляром другого, но поскольку классов нет, вы не можете получить имя класса.

Хотя верно, что в JavaScript нет классов как языковых конструкций, общее соглашение по-прежнему заключается в том, что тип объекта называется классом.

Saul 29.08.2011 10:31

@greg Конечно, но instanceof просто проверяет, наследуется ли объект от других объектов. Например, простой [] наследуется от Array, но Array также наследуется от Object. Поскольку большинство объектов имеют несколько уровней наследования, поиск ближайший прототип - лучший метод. Смотрите мой ответ о том, как.

mikemaccana 15.05.2015 15:13

Ответ Джейсона Бантинга дал мне достаточно подсказок, чтобы найти то, что мне нужно:

<<Object instance>>.constructor.name

Так, например, в следующем фрагменте кода:

function MyObject() {}
var myInstance = new MyObject();

myInstance.constructor.name вернет "MyObject".

Для полноты картины стоит упомянуть, что использование constructor.name работает только в том случае, если вы использовали именованную функцию в качестве конструктора, а не анонимную функцию, назначенную переменной.

Matthew Crumley 02.12.2008 01:24

Для полноты картины стоит упомянуть, что это не работает в браузерах IE - они не поддерживают атрибут «name» в функциях.

Eugene Lazutkin 02.12.2008 06:30

@Eugene - Я забыл об этом ... Думаю, я потратил слишком много времени на создание javascript вне браузеров.

Matthew Crumley 06.12.2008 02:14
function getType(o) { return o && o.constructor && o.constructor.name }
justin.m.chase 03.03.2017 18:39

Это НАСТОЛЬКО всесторонне.

ibic 18.07.2019 10:23

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

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

Да, извините - я удалил его, потому что решил, что instanceof () - лучший способ делать что-то, но я просто восстановил его, чтобы он мог служить ссылкой.

Jason Bunting 02.12.2008 01:30

Менее чем идеальные ответы по-прежнему полезны, хотя бы для других, которые вернутся к вопросу позже, потому что у них есть аналогичная проблема. Так что удалять их действительно не стоит. Сохраните удаления для неправильных ответов.

sblundy 02.12.2008 01:44

Да, я знаю - вы проповедуете хору, я сказал то же самое другим. Жить в соответствии с тем, что мы знаем, часто бывает труднее, чем кажется. :)

Jason Bunting 02.12.2008 01:54

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

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() глобального объекта, чтобы определить тип класса myObject. Использовать это:

Object.prototype.toString.apply(myObject);

Небольшой трюк, который я использую:

function Square(){
    this.className = "Square";
    this.corners = 4;
}

var MySquare = new Square();
console.info(MySquare.className); // "Square"

Мне это не особо нравится. Это больше своего рода подвох. С другой стороны, если у вас не слишком много конструкторов, все может работать нормально.

pimvdb 17.06.2011 11:56

@pimvdb: я думаю, что это чище, чем изменение прототипа объекта, как принятый ответ.

Daniel Szabo 13.05.2013 04:10

@DanielSzabo, если свойство должно иметь одинаковое значение для всех экземпляров прототипа, я определенно предпочитаю просто поместить его в прототип - размещение его в каждом экземпляре является сверхизбыточным, а метаданные отсутствуют в самом прототипе. Тем не менее, самое мудрое решение было принято в ES6: если у вас есть class Square, имя будет Square.name / MySquare.constructor.name, а не Square.prototype.name; помещая name в функцию конструктора, он не загрязняет прототип или какой-либо экземпляр, но доступен из любого из них.

Andy 14.11.2017 02:21

Используйте constructor.name, когда можете, и функцию регулярного выражения, когда я не могу.

Function.prototype.getName = function(){
  if (typeof this.name != 'undefined')
    return this.name;
  else
    return /function (.+)\(/.exec(this.toString())[1];
};

Обновлять

Чтобы быть точным, я думаю, что OP запросил функцию, которая извлекает имя конструктора для определенного объекта. С точки зрения Javascript, object не имеет типа, но является типом из и в себе. Однако разные объекты могут иметь разные конструкторы.

Object.prototype.getConstructorName = function () {
   var str = (this.prototype ? this.prototype.constructor : this.constructor).toString();
   var cname = str.match(/function\s(\w*)/)[1];
   var aliases = ["", "anonymous", "Anonymous"];
   return aliases.indexOf(cname) > -1 ? "Function" : cname;
}

new Array().getConstructorName();  // returns "Array"
(function () {})().getConstructorName(); // returns "Function"


Примечание: в приведенном ниже примере устарел.

Сообщение блога, связанный Кристиан Скиберрас, содержит хороший пример того, как это сделать. А именно, расширяя прототип объекта:

if (!Object.prototype.getClassName) {
    Object.prototype.getClassName = function () {
        return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1];
    }
}

var test = [1,2,3,4,5];

alert(test.getClassName()); // returns Array

Хорошо, но мы снова переходим к именованию: в JS нет классов.

mikemaccana 04.06.2012 17:34

@nailer - рекомендую использовать обновленную функцию, старая сохранена по чисто историческим причинам.

Saul 04.06.2012 17:51

Это работает, но следует отметить, что это можно сделать без изменения Object.prototype, создав функцию, которая принимает объект в качестве первого аргумента и использует его вместо this внутри функции.

Matt Browne 12.11.2012 03:23

@Matt - Конечно. Просто иметь объектный метод проще: test.getClassName() vs getClassName.apply(test).

Saul 12.11.2012 11:54

Вот решение, которое я придумал, которое устраняет недостатки instanceof. Он может проверять типы объекта из кросс-окон и кросс-фреймов и не имеет проблем с примитивными типами.

function getType(o) {
    return Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/)[1];
}
function isInstance(obj, type) {
    var ret = false,
    isTypeAString = getType(type) == "String",
    functionConstructor, i, l, typeArray, context;
    if (!isTypeAString && getType(type) != "Function") {
        throw new TypeError("type argument must be a string or function");
    }
    if (obj !== undefined && obj !== null && obj.constructor) {
        //get the Function constructor
        functionConstructor = obj.constructor;
        while (functionConstructor != functionConstructor.constructor) {
            functionConstructor = functionConstructor.constructor;
        }
        //get the object's window
        context = functionConstructor == Function ? self : functionConstructor("return window")();
        //get the constructor for the type
        if (isTypeAString) {
            //type is a string so we'll build the context (window.Array or window.some.Type)
            for (typeArray = type.split("."), i = 0, l = typeArray.length; i < l && context; i++) {
                context = context[typeArray[i]];
            }
        } else {
            //type is a function so execute the function passing in the object's window
            //the return should be a constructor
            context = type(context);
        }
        //check if the object is an instance of the constructor
        if (context) {
            ret = obj instanceof context;
            if (!ret && (type == "Number" || type == "String" || type == "Boolean")) {
                ret = obj.constructor == context
            }
        }
    }
    return ret;
}

isInstance требует двух параметров: объекта и типа. Настоящая уловка в том, как это работает, заключается в том, что он проверяет, находится ли объект из того же окна, и, если нет, получает окно объекта.

Примеры:

isInstance([], "Array"); //true
isInstance("some string", "String"); //true
isInstance(new Object(), "Object"); //true

function Animal() {}
function Dog() {}
Dog.prototype = new Animal();

isInstance(new Dog(), "Dog"); //true
isInstance(new Dog(), "Animal"); //true
isInstance(new Dog(), "Object"); //true
isInstance(new Animal(), "Dog"); //false

Аргумент типа также может быть функцией обратного вызова, которая возвращает конструктор. Функция обратного вызова получит один параметр, который является окном предоставленного объекта.

Примеры:

//"Arguments" type check
var args = (function() {
    return arguments;
}());

isInstance(args, function(w) {
    return w.Function("return arguments.constructor")();
}); //true

//"NodeList" type check
var nl = document.getElementsByTagName("*");

isInstance(nl, function(w) {
    return w.document.getElementsByTagName("bs").constructor;
}); //true

Следует иметь в виду, что IE <9 не предоставляет конструктор для всех объектов, поэтому приведенный выше тест для NodeList вернет false, а также isInstance (alert, «Функция») вернет false.

Использование Object.prototype.toString

Оказывается, как подробно описано в этом посте, вы можете использовать Object.prototype.toString - низкоуровневую и общую реализацию toString - чтобы получить тип для всех встроенных типов.

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

Можно написать короткую вспомогательную функцию, например

function type(obj){
    return Object.prototype.toString.call(obj]).match(/\s\w+/)[0].trim()
}

return [object String] as String
return [object Number] as Number
return [object Object] as Object
return [object Undefined] as Undefined
return [object Function] as Function

Вам не нужно использовать регулярное выражение для анализа имени объекта. Просто используйте .slice(): Object.prototype.toString.call(obj).slice( 8, -1 );

bobobobo 03.01.2018 21:39

Функция Добрый() из Agave.JS вернет:

  • ближайший прототип в дереве наследования
  • для всегда примитивных типов, таких как 'null' и 'undefined', имя примитива.

Он работает со всеми объектами и примитивами JS, независимо от того, как они были созданы, и не вызывает никаких сюрпризов. Примеры:

Числа

kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'

NaN

kind(NaN) === 'NaN'

Струны

kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'

Булевы

kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'

Массивы

kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'

Объекты

kind({a:1}) === 'Object'
kind(new Object()) === 'Object'

Даты

kind(new Date()) === 'Date'

Функции

kind(function(){}) === 'Function'
kind(new Function("console.info(arguments)")) === 'Function'
kind(Math.sin) === 'Function'

неопределенный

kind(undefined) === 'undefined'

нулевой

kind(null) === 'null'

Я действительно искал похожую вещь и наткнулся на этот вопрос. Вот как я получаю типы: jsfiddle

var TypeOf = function ( thing ) {

    var typeOfThing = typeof thing;

    if ( 'object' === typeOfThing ) {

        typeOfThing = Object.prototype.toString.call( thing );

        if ( '[object Object]' === typeOfThing ) {

            if ( thing.constructor.name ) {
                return thing.constructor.name;
            } 

            else if ( '[' === thing.constructor.toString().charAt(0) ) {
                typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
            } 

            else {

                typeOfThing = thing.constructor.toString().match( /function\s*(\w+)/ );

                if ( typeOfThing ) { 
                    return typeOfThing[1];
                } 

                else {
                    return 'Function';
                }
            }
        } 

        else {
            typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
        }
    }

    return typeOfThing.charAt(0).toUpperCase() + typeOfThing.slice(1);
}

Если кто-то искал решение, работающее с 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] : "";
    }
});

Да, jQuery не может выполнить проверку hasOwnProperty, поэтому перечисляет getName и падает.

nicodemus13 23.09.2015 18:21

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 метод, называемый "identify", который работает следующим образом:

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

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

Хорошо, ребята, я несколько лет медленно создавал для этого метод улова всех, лол! Уловка заключается в следующем:

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

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

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

Как вы можете видеть, у меня есть некоторые механизмы, чтобы заставить classOf всегда предоставлять мне имя типа классов / конструкторов независимо от того, является ли он примитивом, определяемым пользователем классом, значением, созданным с использованием собственного конструктора, 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 и т. д.).

Удачного кодирования!

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

/**
 * 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\s+([^(]+)?\(/;
    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\s+([^(]+)?\(/;
    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\s+([^(]+)?\(/;
  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.info("getTypeName(undefined): " + getTypeName(undefined));
console.info("getTypeName(null): " + getTypeName(null));
console.info("getTypeName(true): " + getTypeName(true));
console.info("getTypeName(5): " + getTypeName(5));
console.info("getTypeName(\"text\"): " + getTypeName("text"));
console.info("getTypeName(userFunction): " + getTypeName(UserFunction));
console.info("getFunctionName(userFunction): " + getFunctionName(UserFunction));
console.info("getTypeName(anonymousFunction): " + getTypeName(anonymousFunction));
console.info("getFunctionName(anonymousFunction): " + getFunctionName(anonymousFunction));
console.info("getTypeName(arrowFunction): " + getTypeName(arrowFunction));
console.info("getFunctionName(arrowFunction): " + getFunctionName(arrowFunction));
//console.info("getFunctionName(userClass): " + getFunctionName(new UserClass()));
console.info("getTypeName(userClass): " + getTypeName(new UserClass()));
console.info("getObjectClass(userClass): " + getObjectClass(new UserClass()));
//console.info("getObjectClass(userFunction): " + getObjectClass(UserFunction));
//console.info("getObjectClass(userFunction): " + getObjectClass(anonymousFunction));
//console.info("getObjectClass(arrowFunction): " + getObjectClass(arrowFunction));
console.info("getTypeName(nativeObject): " + getTypeName(navigator.mediaDevices.getUserMedia));
console.info("getFunctionName(nativeObject): " + getFunctionName(navigator.mediaDevices.getUserMedia));

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

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

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

Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');

Вы должны использовать 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.info(res1); // 'date'
    console.info(res2); // 'number'
    console.info(res3); // 'function'

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

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

function TestB() {}
console.info(TestB.name); // "TestB"

В вопросе четко написано class, а не экземпляр.

qwertzguy 07.02.2020 23:22

Довольно простой!

  • Мой любимый способ получить что-нибудь в JS
function getType(entity){
    var x = Object.prototype.toString.call(entity)
    return x.split(" ")[1].split(']')[0].toLowerCase()
}
  • мой любимый метод проверки типа чего-либо в JS
function checkType(entity, type){
    return getType(entity) === type
}

Для тех из вас, кто читает это и хочет простое решение, которое достаточно хорошо работает и было протестировано:

const getTypeName = (thing) => {
  const name = typeof thing
  if (name !== 'object') return name
  if (thing instanceof Error) return 'error'
  if (!thing) return 'null'
  return ({}).toString.call(thing).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

Чтобы понять, почему это работает, ознакомьтесь с документацией по полифилу для Array.isArray (): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray#polyfill

Другие вопросы по теме