Отримайте назву типу об’єкта


1193

Чи є JavaScript еквівалент Java «з class.getName()?


Це питання передбачає, що ми знаємо, що робить Java class.getName (). Оскільки я не знаю, я не впевнений, чи допоможуть мені відповіді.
користувач34660

2
@ user34660 Я думаю, що ми можемо сміливо припускати, що те, що він робить, - це назва типу об’єкта.
Стік Underflow

1
@StackUnderflow: За винятком того, що насправді немає. Він отримує ім'я об'єкта класу , який НЕ такі ж , як об'єкт типу .
Йорг W Міттаг

1
@ JörgWMittag Ага так, звичайно. Я бачите, що станеться, коли ви обходите безпечно припускаючи речі?
Stack згущеного

Відповіді:


1540

Чи існує еквівалент JavaScript у Java class.getName()?

Ні .

ES2015 Update : ім'я class Foo {}ISFoo.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власності ...

Не працює ВСЕ у багатьох випадках

Знову див. Вище; Це цілком звичайно, 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 місяці після опублікування статті, це рекомендована версія для використання автором статті Меттью Шарлі. Ця зміна надихнула коментарів, які вказували на можливі підводні камені в попередньому коді.

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
Що ж, я вважав, що це теж можливо - сенс Stack Overflow - це трохи схожий на вікі, і це набагато більше відповідає тому наміру. Незалежно, я просто хотів бути дещо ретельним.
Джейсон Бантінг

Повторне повторення відповіді нижче --- ваше розширення до прототипу Object не працює в IE8 - хтось знає, що буде працювати в IE8?
Адам

5
Він буде працювати, якщо ви зробите це так, як ця функція a () {this.a = 1;} функція b () {this.b = 2; } b.prototype = новий a (); // b успадковує від b.prototype.constructor = b; // Правильний спосіб прототипічного успадкування var f = new b (); // створити новий об’єкт за допомогою конструктора b (f.constructor == b); // ІСТИНА (f.constructor == a); //
ФАЛЬС

9
Тепер саме так, більшість відповідей має бути на StackOverflow. (не сприймайте довжину відповіді як визначальний параметр, але всебічність)
kumarharsh

44
Важливо відзначити , що будь-які методи , які інспектувати об'єкт constructorметод (або .toString()чи .name) не працюватимуть , якщо ваш Javascript був мінімізований за допомогою інструменту , як спотворювати або трубопровід активів 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
@Eugene - я забув про це ... я думаю, що я витратив занадто багато часу, роблячи 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

Оновлення

Якщо бути точним, я думаю, що ОП попросив функцію, яка отримує назву конструктора для певного об'єкта. З точки зору 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, створивши функцію, яка приймає об'єкт як перший аргумент і використовує його замість 'цього' всередині функції.
Метт Браун

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

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 поверне помилковим, а також isInstance (попередження, «Функція») поверне помилковим.


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'

нуль

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", щоб визначити, об'єкт є екземпляром певного класу чи ні. Якщо ви не знаєте назви типу об’єкта, ви можете використовувати його властивість конструктора. Властивість конструктора об'єктів - це посилання на функцію, яка використовується для їх ініціалізації. Приклад:

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властивість Object .



2
Менш ніж ідеальні відповіді все-таки корисні, якщо тільки до інших прийти до питання пізніше, оскільки вони мають подібну проблему. Тому ви дійсно не повинні їх видаляти. Збережіть видалених для неправильних відповідей.
sblundy

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

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] : "";
    }
});

Так, jQuery не може зробити перевірку "hasOwnProperty" і так перелічує getNameі перепадає.
nicodemus13

0

У Лодаша є багато методів is, тому якщо ви використовуєте 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;
      }
  });

Він додає метод подачі називати "ідентифікувати", який працює наступним чином:

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

Plunker: 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 - остаточний посібник." Девід Фланаган. - та багато інших .. (search le` web).

Також ви можете швидко перевірити функції, про які я тут говорю: - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (також шлях 0,5.18 в URL-адресі має джерела з github там мінус node_модулі тощо.

Щасливе кодування!


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.