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


1193

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


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

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

1
@StackUnderflow: за исключением того, что на самом деле это не так. Он получает имя объекта класса , который не такие же , как объект типа .
Йорг Миттаг

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

Ответы:


1540

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

Нет .

ES2015 Обновление : имя class Foo {}естьFoo.name . Имя класса thing's', независимо от thingтипа 's', равно thing.constructor.name. Встроенные конструкторы в среде ES2015 имеют правильное nameсвойство; например (2).constructor.nameесть "Number".


Но вот различные хаки, которые все так или иначе падают:

Вот хак, который сделает то, что вам нужно - помните, что он изменяет прототип Объекта, что люди не одобряют (обычно по уважительной причине)

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

Теперь все ваши объекты будут иметь функцию, getName()которая будет возвращать имя конструктора в виде строки. Я проверил это в, FF3и IE7я не могу говорить о других реализациях.

Если вы не хотите этого делать, вот обсуждение различных способов определения типов в JavaScript ...


Я недавно обновил это, чтобы быть немного более исчерпывающим, хотя вряд ли это. Исправления приветствуются ...

Используя constructorсвойство ...

У каждого objectесть значение для его constructorсвойства, но в зависимости от того, как оно objectбыло построено, а также от того, что вы хотите сделать с этим значением, оно может быть или не быть полезным.

Вообще говоря, вы можете использовать constructorсвойство для проверки типа объекта следующим образом:

var myArray = [1,2,3];
(myArray.constructor == Array); // true

Итак, это работает достаточно хорошо для большинства потребностей. Это сказал ...

Предостережения

Во многих случаях не будет работать ВСЕ

Этот паттерн, хотя и нарушен, довольно распространен:

function Thingy() {
}
Thingy.prototype = {
    method1: function() {
    },
    method2: function() {
    }
};

Objectsпостроенный через new Thingyбудет иметь constructorсвойство, которое указывает Object, а не Thingy. Таким образом, мы падаем с самого начала; вы просто не можете доверять constructorкодовой базе, которую вы не контролируете.

Множественное наследование

Пример, где это не так очевидно, использует множественное наследование:

function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a

Вещи теперь не работают, как вы могли бы ожидать, что они:

var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true

Таким образом, вы можете получить неожиданные результаты, если objectваш тест имеет другой objectнабор prototype. Есть способы обойти это за рамками этого обсуждения.

Существуют и другие варианты использования constructorнедвижимости, некоторые из которых интересны, другие не так уж много; сейчас мы не будем углубляться в это использование, поскольку оно не имеет отношения к этому обсуждению.

Не будет работать поперечина и поперечное окно

Использование .constructorпроверки типа прекратит работу, если вы захотите проверить тип объектов, поступающих из разных windowобъектов, например, из iframe или всплывающего окна. Это потому, что constructorв каждом «окне» есть разные версии каждого типа ядра , т.е.

iframe.contentWindow.Array === Array // false

Использование instanceofоператора ...

instanceofОператор чистый способ тестирования objectтипа , а также, но имеет свои собственные потенциальные проблемы, так же , как constructorсобственность.

var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true

Но instanceofне работает для литеральных значений (потому что литералы нет Objects)

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false

Например, литералы должны быть обернуты Objectв, instanceofчтобы работать

new Number(3) instanceof Number // true

.constructorПроверка работает отлично литералы , так как .вызов методы неявно упаковывает литералы в соответствующем типе объекта

3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true

Почему две точки для 3? Потому что Javascript интерпретирует первую точку как десятичную точку;)

Не будет работать поперечина и поперечное окно

instanceofтакже не будет работать в разных окнах по той же причине, что и constructorпроверка свойства.


Используя nameсобственность constructorсобственности ...

Не работает на всех во многих случаях

Опять же, смотрите выше; это довольно распространено для того, constructorчтобы быть совершенно и совершенно неправильным и бесполезным.

НЕ работает в <IE9

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

Для IE9 и выше вы можете использовать monkey-patch в поддержке :

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s+([^\s(]+)\s*\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1] : "";
        },
        set: function(value) {}
    });
}

Обновленная версия из рассматриваемой статьи. Это было добавлено через 3 месяца после публикации статьи, это рекомендуемая версия для использования автором статьи Мэтью Шарли. Это изменение было вдохновлено комментариями, указывающими на возможные подводные камни в предыдущем коде.

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s([^(]{1,})\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1].trim() : "";
        },
        set: function(value) {}
    });
}

Использование 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).slice(8, -1);
}

убрать фуфло и получить только название типа

type('abc') // String

Тем не менее, он вернется Objectдля всех пользовательских типов.


Предостережения для всех ...

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

// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // true
(obj.constructor.name == "Foo");  // true

// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // false
(obj.constructor.name == "Foo");  // false


// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object);              // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == "");         // true


// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object);      // true
(obj instanceof Foo);         // true
(obj.constructor == Foo);     // true
(obj.constructor.name == ""); // true


// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object);            // true
(obj.constructor == Object);        // true
(obj.constructor.name == "Object"); // true

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

НОТА:

Обсуждение typeofоператора может показаться явным упущением, но на самом деле бесполезно помогать определить, objectявляется ли тип заданным, поскольку оно очень упрощенное. Понимание того, где typeofэто полезно, важно, но в настоящее время я не чувствую, что это очень важно для этой дискуссии. Мой разум открыт для изменения, хотя. :)


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

Повторяя ответ ниже - ваше расширение к прототипу Object не работает в IE8 - кто-нибудь знает, что будет работать в IE8?
Адам

5
Это будет работать, если вы сделаете это как эта функция a () {this.a = 1;} function b () {this.b = 2; } b.prototype = new a (); // b наследуется от b.prototype.constructor = b; // Правильный способ наследования прототипа var f = new b (); // создаем новый объект с помощью конструктора b (f.constructor == b); // TRUE (f.constructor == a); // ЛОЖЬ
Борис Гаманов

9
Теперь вот как большинство ответов должно быть в StackOverflow. (не принимайте длину ответа в качестве определяющего параметра, а исчерпывающую информацию)
kumarharsh

44
Важно отметить, что любые методы, которые проверяют метод объекта constructor(либо с помощью, .toString()либо .name), не будут работать, если ваш Javascript был уменьшен с помощью такого инструмента, как uglify, или конвейер ресурсов Rails. Минификация переименовывает конструктор, поэтому вы получите неправильные имена классов, такие как n. Если вы находитесь в этом сценарии, вы можете просто вручную определить classNameсвойство ваших объектов и использовать его вместо этого.
Гейб Мартин-Демпси

126

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

<<Object instance>>.constructor.name

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

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

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


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

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

2
@ Евгений - я забыл об этом ... я думаю, что слишком много времени занимался написанием javascript вне браузеров.
Мэтью Крамли

2
function getType(o) { return o && o.constructor && o.constructor.name }
justin.m.chase

Это настолько всеобъемлющий.
ibic

26

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

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

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

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

13
@pimvdb: я думаю, что это чище, чем модифицировать прототип объекта, а-ля принятый ответ.
Даниэль Сзабо

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

17

Обновить

Чтобы быть точным, я думаю, что 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"

 


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

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

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

2
Хорошо, но мы снова в названии: у JS нет классов.
mikemaccana

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

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

2
@Matt - Конечно. Просто метод объекта более лаконичен: test.getClassName()против getClassName.apply(test).
Сол

12

Использование 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

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

9

Вот решение, которое я придумала, которое решает недостатки 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, "Function") вернул бы false.


8

Я на самом деле искал похожую вещь и наткнулся на этот вопрос. Вот как я получаю типы: 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);
}

7

Вы должны использовать 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'


6

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

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

6

Функция kind () из 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.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'

не определено

kind(undefined) === 'undefined'

значение NULL

kind(null) === 'null'

5

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


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

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

4

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

/**
 * 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

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

Object.prototype.toString.apply(myObject);

3

Скажи у тебя есть var obj;

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

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

2

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

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


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

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

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

0

Если кто-то искал решение, которое работает с 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

0

В 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

Плункер: http://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN


0

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

  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 и тому подобное).

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


0

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

  • Мой любимый способ получить тип чего-либо в 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
}

-1

Использование class.name. Это также работает с function.name.

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

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

Вопрос четко говорит, classа не экземпляр.
qwertzguy
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.