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

1173

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

  • 0
    Этот вопрос предполагает, что мы знаем, что делает Java class.getName (). Так как я не уверен, я не уверен, что ответы помогут мне.
  • 1
    @ user34660 Я думаю, мы можем с уверенностью предположить, что он получает имя типа объекта.
Теги:

19 ответов

1545
Лучший ответ

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

Нет.

Обновление ES2015: имя class Foo {} равно Foo.name. Имя класса thing, независимо от типа thing, равно 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...

Во многих случаях не работает AT ALL

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

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

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

Для IE9 и выше вы можете обезьян-патч в поддержке:

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 месяца после публикации статьи, это рекомендуемая версия для использования автором статьи Matthew Scharley. Это изменение было вызвано комментариями указывающими потенциальные ловушки в предыдущем коде.

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);
}

чтобы удалить cruft и получить только имя типа

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

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

Примечание:

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

  • 56
    Ну, я подумал, что мог бы также - смысл переполнения стека - быть немного похожим на вики, и это, скорее всего, соответствует этой цели, я думаю. Несмотря на это, я просто хотел быть более тщательным.
  • 0
    Повторяя ответ ниже - ваше расширение к прототипу Object не работает в IE8 - кто-нибудь знает, что будет работать в IE8?
Показать ещё 16 комментариев
112

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

<<Object instance>>.constructor.name

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

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

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

  • 21
    Для полноты картины стоит упомянуть, что использование constructor.name работает только в том случае, если вы использовали именованную функцию в качестве конструктора, а не анонимную функцию, назначенную переменной.
  • 20
    Для полноты картины стоит упомянуть, что он не работает в браузерах IE - они не поддерживают атрибут «name» в функциях.
Показать ещё 3 комментария
25

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

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

var MySquare = new Square();
console.log(MySquare.className); // "Square"
  • 10
    Мне это не особо нравится. Это скорее своего рода подвох. С другой стороны, если у вас не слишком много конструкторов, это может работать просто отлично.
  • 12
    @pimvdb: я думаю, что это чище, чем модифицировать прототип объекта, а-ля принятый ответ.
Показать ещё 1 комментарий
17

Update

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

 


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

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

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 нет классов.
  • 0
    @nailer - я рекомендую использовать обновленную функцию, старая хранится только по историческим причинам.
Показать ещё 2 комментария
11

Использование 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
  • 4
    Вам не нужно использовать регулярное выражение для анализа имени объекта. Просто используйте .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 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 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.

7

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

Booleans

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'

undefined

kind(undefined) === 'undefined'

NULL

kind(null) === 'null'
6

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

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

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

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

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

/**
 * Returns the name of an object 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 class
 * @see <a href="/questions/10993/how-do-i-get-the-name-of-an-objects-type-in-javascript/74371#74371">/questions/10993/how-do-i-get-the-name-of-an-objects-type-in-javascript/74371#74371</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 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 global. Например, если у вас есть объект, скажите myObject, вы можете использовать метод toString() глобального объекта Object для определения типа класса myObject. Используйте это:

Object.prototype.toString.apply(myObject);
2

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

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

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

  • 0
    Да, извините - я удалил его, потому что я подумал, что instanceof () - лучший способ сделать что-то, но я просто восстановил его, чтобы он мог послужить ссылкой.
  • 2
    Недостаточно точные ответы все еще полезны, хотя бы для того, чтобы другие позже приходили к вопросу, потому что у них похожая проблема. Таким образом, вы действительно не должны удалять их. Сохранить удаляет за неправильные ответы.
Показать ещё 1 комментарий
1

Скажите, что у вас есть var obj;

Если вам просто нужно имя типа obj, например "Object", "Array" или "String", вы можете использовать это:

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

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

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

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

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

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

В качестве примера (или чтобы посмотреть, как я столкнулся с проблемой) рассмотрим следующий код в 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 name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!

`` `

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

Также книги с содержанием по теме: - "Шаблоны JavaScript" Стояна Стефанова. - "Javascript - окончательное руководство". Дэвидом Фланаганом. - и многие другие.. (поиск le` web).

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

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

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

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

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

0

Если кто-то искал решение, которое работает с jQuery, вот отрегулированный код wiki (исходный разрыв 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] : "";
    }
});
  • 0
    Да, jQuery не может выполнить проверку hasOwnProperty и поэтому перечисляет getName и падает.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню