Bir nesnenin türünün adını alma


1193

Bir var mı JavaScript eşdeğer Java'nın 's class.getName()?


Bu soru, Java'nın class.getName () yönteminin ne yaptığını bildiğimizi varsayar. Yapmadığım için cevapların bana yardımcı olup olmayacağından emin değilim.
user34660

2
@ user34660 Sanırım yaptığı şeyin bir nesnenin türünün adını aldığını güvenli bir şekilde varsayabiliriz.
Stack

1
@StackUnderflow: Aslında öyle değil. Bir nesnenin adını alır sınıfına olduğunu değil bir nesnenin aynı tip .
Jörg W Mittag

1
@ JörgWMittag Ah evet, elbette. Bir şeyleri güvenli bir şekilde varsayarsak ne olur görüyor musun?
Stack

Yanıtlar:


1540

Java'nın JavaScript eşdeğeri var class.getName()mı?

Hayır .

ES2015 Güncelleme : adı class Foo {}DİRFoo.name . thing'S sınıfının adı, thingtüründen bağımsız olarak thing.constructor.name. ES2015 ortamındaki yerleşik yapıcılar doğru nameözelliğe sahiptir; Mesela (2).constructor.nameolduğunu "Number".


Ama işte hepsi öyle ya da böyle düşüyor:

İşte ihtiyacınız olanı yapacak bir kesmek - Nesnenin prototipini değiştirdiğini, insanların kaşlarını çattığının farkında olun (genellikle iyi bir nedenden dolayı)

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

Şimdi, tüm nesneleriniz getName(), yapıcı adını dize olarak döndürecek bir işleve sahip olacaktır. Bunu test ettim FF3ve IE7başka uygulamalar için konuşamam.

Bunu yapmak istemiyorsanız, JavaScript'teki türleri belirlemenin çeşitli yolları hakkında bir tartışma ...


Son zamanlarda bunu biraz daha kapsamlı olması için güncelledim, ancak pek de zor değil. Düzeltmeler hoş geldiniz ...

Kullanımı constructorözelliği ...

Her objectbirinin constructormülkü için bir değeri vardır , ancak bunun nasıl objectinşa edildiğine ve bu değerle ne yapmak istediğinize bağlı olarak, yararlı olabilir veya olmayabilir.

Genel olarak konuşursak, constructorözelliği nesnenin türünü şu şekilde test etmek için kullanabilirsiniz :

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

Bu, çoğu ihtiyaç için yeterince iyi çalışıyor. Bahsedilen...

Uyarılar

Birçok durumda TÜMÜNDE çalışmaz

Bu desen kırılmış olsa da oldukça yaygındır:

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

Objectsüzerinden inşa edilen new Thingybir constructorözelliği gösterir Object, değil Thingy. Bu yüzden en başından düşüyoruz; sadece güvenemezsinconstructorkontrol etmediğin bir kod tabanına .

Çoklu Kalıtım

Çok açık olmadığı bir örnek birden fazla miras kullanmaktır:

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

Artık işler beklediğiniz gibi çalışmıyor:

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

Bu nedenle, objecttestinizde farklı bir objectset varsa beklenmedik sonuçlar alabilirsiniz prototype. Bu tartışmanın kapsamı dışında bunun dışında yollar var.

constructorMülk için bazı kullanımları vardır , bazıları ilginç, diğerleri çok fazla değil; şimdilik bu tartışmalarla ilgili olmadığı için bu kullanımları araştırmayacağız.

Çapraz çerçeve ve çapraz pencere çalışmaz

.constructorFarklı gelen nesnelerin türünü kontrol etmek istediğinizde tür denetimi için kullanılmasıwindow nesnelerden , örneğin iframe veya açılır pencerenin . Bunun nedeni constructor, her bir `` pencerede '' her çekirdek türünün farklı bir sürümünün olmasıdır , yani

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

instanceofOperatörü kullanma ...

instanceofOperatör test temiz bir yoludur object, tıpkı yanı tipini ancak kendi potansiyel sorunları vardırconstructor mülkiyet.

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

Ancak instanceofdeğişmez değerler için çalışmaz (çünkü değişmez değerlerObjects )

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

Değişmez değerlerin bir Objectsırayla sarılması gerekir.instanceof örneğin, iş için

new Number(3) instanceof Number // true

.constructorÇek nedeniyle değişmezleri cezasını işleri. yöntem çağırma örtük kendi nesne türü değişmezleri sarar

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

Neden 3 için iki nokta? Çünkü Javascript ilk noktayı ondalık nokta olarak yorumlar;)

Çapraz çerçeve ve çapraz pencere çalışmaz

instanceofAyrıca, constructorözellik kontrolü ile aynı nedenden dolayı farklı pencerelerde çalışmaz .


nameMülkiyetini kullanmaconstructor ...

Çalışmaz AT ALLBirçok durumda

Yine, yukarıya bakınız; için oldukça yaygınconstructortamamen ve tamamen yanlış ve işe yaramaz olması .

<IE9'da ÇALIŞMIYOR

Kullanmak myObjectInstance.constructor.name, constructorkullanılan işlevin adını içeren bir dize verecektir , ancak constructordaha önce belirtilen özellik hakkındaki uyarılara tabidir .

IE9 ve üstü için destekte maymun yaması yapabilirsiniz :

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

Söz konusu makaleden güncellenmiş sürüm . Bu, makalenin yayınlanmasından 3 ay sonra eklendi, bu makalenin yazarı Matthew Scharley tarafından kullanılması önerilen sürümdür. Bu değişiklik, önceki koddaki potansiyel tuzaklara işaret eden yorumlardan ilham aldı.

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 kullanma

Bu gönderi ayrıntılarında olduğu gibi , tüm yerleşik türlerin türünü almak için - Object.prototype.toStringdüşük seviye ve genel uygulamayı toString- kullanabilirsiniz

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

Biri gibi kısa bir yardımcı fonksiyon yazabilir

function type(obj){
    return Object.prototype.toString.call(obj).slice(8, -1);
}

hamuru kaldırmak ve sadece tip adına ulaşmak için

type('abc') // String

Ancak, Objecttüm kullanıcı tanımlı türler için geri döner .


Herkes için uyarılar ...

Bunların hepsi bir potansiyel soruna tabidir ve bu, söz konusu nesnenin nasıl inşa edildiği sorusudur. Nesneleri oluşturmanın çeşitli yolları ve farklı tür denetimi yöntemlerinin döndüreceği değerler şunlardır:

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

Bu örnek kümesinde tüm permütasyonlar mevcut olmasa da, umarım ihtiyaçlarınıza bağlı olarak dağınık şeylerin nasıl olabileceği konusunda size bir fikir vermeniz yeterlidir. Hiçbir şey varsaymayın, tam olarak neyin peşinde olduğunuzu anlamadıysanız, inceliklerin yutulmaması nedeniyle beklemediğiniz yerde kod kırma ile sonuçlanabilir.

NOT:

typeofOperatörün tartışması göze batan bir ihmal gibi görünebilir, ancak an'ın objectbelirli bir tür olup olmadığını tanımlamakta gerçekten yararlı değildir , çünkü çok basittir. Nerede typeofyararlı olduğunu anlamak önemlidir, ancak şu anda bu tartışmayla çok ilgili olduğunu düşünmüyorum. Aklım değişime açık. :)


58
Ben de düşündüm ki, Stack Overflow'un amacı bir wiki gibi olmaktır ve bence bu amaç doğrultusunda çok daha fazlası. Ne olursa olsun, sadece biraz ayrıntılı olmak istedim.
Jason Bunting

Aşağıdaki cevabı tekrarlamak --- Nesne prototipine olan uzantınız IE8'de çalışmıyor - IE8'de ne işe yarayacağını bilen var mı?
Adam

5
Bu işlev gibi yaparsanız çalışır (a () {this.a = 1;} işlev b () {this.b = 2; } b.prototype = new a (); // b bir b.prototype.constructor = b'den miras alır; // Prototipik mirasın doğru yolu var f = new b (); // b yapıcısı ile yeni nesne oluştur (f.constructor == b); // TRUE (f.constructor == a); // YANLIŞ
Boris Hamanov

9
Şimdi, cevapların çoğu StackOverflow'da böyle olmalıdır. (cevabın uzunluğunu tanımlayıcı bir parametre olarak değil, kapsamlılık olarak
almayın

44
Bu nesnenin incelemek herhangi teknikler o notta önemlidir constructor(ile ya yöntemini .toString()veya .namesizin JavaScript çirkinleştirmek gibi bir araç veya Raylar varlık boru hattı ile minified edilmişse) işe başarısız olur. Mination yapıcıyı yeniden adlandırır, böylece gibi yanlış sınıf isimleri elde edersiniz n. Bu senaryodaysanız, nesnelerinizde bir özelliği el ile tanımlamak classNameve bunun yerine bunu kullanmak isteyebilirsiniz .
Gabe Martin-Dempesy

126

Jason Bunting'in cevabı bana ihtiyacım olanı bulmak için yeterince ipucu verdi:

<<Object instance>>.constructor.name

Yani, örneğin, aşağıdaki kod parçasında:

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

myInstance.constructor.namedönecekti "MyObject".


22
Tamlık için, constructor.name kullanmanın yalnızca bir değişkene atanan anonim bir işlevin aksine yapıcı olarak adlandırılmış bir işlev kullandığınızda işe yaradığını belirtmek gerekir.
Matthew Crumley

20
Tamlık için, IE tarayıcılarında çalışmadığından bahsetmeye değer olabilir - fonksiyonlarda "name" özelliğini desteklemezler.
Eugene Lazutkin

2
@Eugene - Bunu unuttum ... Sanırım tarayıcıların dışında javascript yapmak için çok fazla zaman harcadım.
Matthew Crumley

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

Bu çok kapsamlı.
ibic

26

Kullandığım küçük bir numara:

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

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

11
Özellikle bunu sevmiyorum. Daha çok kirli bir numara. Öte yandan, çok fazla kurucunuz yoksa, işe yarayabilir.
pimvdb

13
@pimvdb: Bence nesnenin prototipini değiştirmekten daha temiz, kabul edilen bir cevap.
Daniel Szabo

4
@DanielSzabo bir mülkün bir prototipin tüm örnekleri arasında aynı değere sahip olması gerekiyorsa, kesinlikle sadece prototipe koymayı tercih ederim - her örneğe koymak çok fazladır ve meta veriler prototipin kendisinde eksiktir. Bununla birlikte, en akıllı çözüm ES6'da kabul edildi: eğer varsa class Square, isim Square.name/ MySquare.constructor.nameyerine Square.prototype.name; koyarak nameyapıcı fonksiyonu üzerine bu prototip veya herhangi bir örneğini kirletmez, fakat birinden erişilebilir.
Andy

17

Güncelleme

Kesin olmak gerekirse, OP'nin belirli bir nesne için yapıcı adını alan bir işlev istediğini düşünüyorum. Javascript açısından, objectbir türü yoktur, ancak kendi içinde ve kendisidir . Ancak, farklı nesnelerin farklı kurucuları olabilir .

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"

 


Not: Aşağıdaki örnek kullanımdan kaldırılmıştır.

Christian Sciberras tarafından bağlanan bir blog yazısı , bunun nasıl yapılacağına dair iyi bir örnek içerir. Yani, Object prototipini genişleterek:

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
Güzel, ama tekrar adlandırıyoruz: JS'de ders yok.
mikemaccana

@nailer - Güncellenmiş işlevi kullanmanızı öneririm, eskisi yalnızca tarihi nedenlerle saklanır.
Saul

Bu işe yarıyor ancak Object.prototype değiştirilmeden, nesneyi ilk argüman olarak alan ve işlev içinde 'this' yerine bunu kullanan bir işlev oluşturularak yapılabileceği belirtilmelidir.
Matt Browne

2
@Matt - Elbette. : Bu, nesne yöntem sahip daha kısa ve öz sadece olmasıdır test.getClassName()vs getClassName.apply(test).
Saul

12

Object.prototype.toString kullanma

Bu gönderi ayrıntılarında olduğu gibi, tüm yerleşik türlerin türünü almak için Object.prototype.toString'i - toString'in düşük düzeyli ve genel uygulaması - kullanabilirsiniz.

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

Biri gibi kısa bir yardımcı fonksiyon yazabilir

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
Nesne adını ayrıştırmak için regex kullanmanıza gerek yoktur. Sadece kullanın .slice():Object.prototype.toString.call(obj).slice( 8, -1 );
bobobobo

9

İşte ortaya koyduğum ve instanceof'in eksikliklerini çözen bir çözüm. Bir nesnenin türlerini çapraz pencerelerden ve çapraz çerçevelerden kontrol edebilir ve ilkel türlerle ilgili problemleri yoktur.

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 iki parametre gerektirir: bir nesne ve bir tür. Nasıl çalıştığının asıl püf noktası, nesnenin aynı pencereden olup olmadığını ve nesnenin penceresini alıp almadığını kontrol etmesidir.

Örnekler:

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

Type argümanı ayrıca bir kurucu döndüren bir geri çağırma işlevi olabilir. Geri arama işlevi, sağlanan nesnenin penceresi olan bir parametre alır.

Örnekler:

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

Akılda tutulması gereken bir şey, IE <9'un tüm nesneler üzerinde yapıcıyı sağlamamasıdır, böylece NodeList için yukarıdaki test yanlış döndürür ve ayrıca bir isInstance (alert, "Function") false döndürür.


8

Aslında benzer bir şey arıyordum ve bu soruya rastladım. Nasıl tür olsun: 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

Şunun somevar.constructor.namegibi kullanmalısınız :

    
    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

Yapabildiğiniz constructor.namezaman kullanın ve yapamadığımda regex işlevi.

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

6

Tür () dan işlev Agave.JS döndürür:

  • miras ağacındaki en yakın prototip
  • 'null' ve 'undefined' gibi her zaman ilkel türler için ilkel ad.

Nasıl oluşturulduklarına bakılmaksızın tüm JS nesneleri ve ilkelleri üzerinde çalışır ve sürprizleri yoktur. Örnekler:

sayılar

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'

Teller

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

Boolean

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

Diziler

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

Nesneler

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

Tarih

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

Fonksiyonlar

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

Tanımsız

kind(undefined) === 'undefined'

boş

kind(null) === 'null'

5

instanceofBir nesnenin başka bir örnek olup olmadığını görmek için işleci kullanabilirsiniz , ancak sınıf olmadığından sınıf adı alamazsınız.


JavaScript'in dil yapısı olarak sınıfları olmadığı doğru olsa da, genel kural yine de bir nesne türünün sınıf olarak adlandırılmasıdır.
Saul

2
@greg Elbette, ancak instanceofbir nesnenin başka bir nesneden miras alıp almadığını kontrol eder. Örneğin, basit bir şekilde []Array'den miras alır, ancak Array da Object'den miras alır. Çoğu nesnenin birden fazla kalıtım düzeyi olduğundan, en yakın prototipi bulmak daha iyi bir tekniktir. Nasıl olduğunu öğrenmek için cevabımı görün.
mikemaccana

4

Kabul edilen cevaba dayanan bir uygulama :

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

Yapıcı özelliğini yalnızca başka seçeneğimiz olmadığında kullanırız.


3

Bir nesnenin belirli bir sınıfın örneği olup olmadığını belirlemek için "instanceof" operatörünü kullanabilirsiniz. Bir nesnenin türünün adını bilmiyorsanız, onun yapıcı özelliğini kullanabilirsiniz. Nesnelerin yapıcı özelliği, onları başlatmak için kullanılan işleve bir referanstır. Misal:

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

Şimdi c1.constructor işleve bir referanstır Circle(). typeofİşleci de kullanabilirsiniz , ancak typeofoperatör sınırlı bilgi gösterir. Bir çözüm, toString()Object global nesnesinin yöntemini kullanmaktır . Örneğin, myObject gibi bir nesneniz varsa, myObject toString()sınıfının türünü belirlemek için global Object yöntemini kullanabilirsiniz . Bunu kullan:

Object.prototype.toString.apply(myObject);

3

Söyle var var obj;

"Nesne", "Dizi" veya "Dize" gibi obj türünün adını istiyorsanız, bunu kullanabilirsiniz:

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

2

Alabileceğiniz en yakın şey typeof, ancak herhangi bir özel tür için yalnızca "nesne" döndürür. Bunlar için Jason Bunting'e bakınız .

Düzenleyin, Jason'ın gönderisini herhangi bir nedenle sildi, bu yüzden Object'in constructorözelliğini kullanın .


Evet, üzgünüm - instanceof () işlevini yapmanın daha iyi bir yolu olduğunu düşündüğüm için sildim, ancak referans olarak kullanılabilmesi için silme işlemini geri aldım.
Jason Bunting

2
Sadece daha sonra başkalarına da benzer bir problemleri olduğu için soru sormak için mükemmel cevaplardan daha azı faydalıdır. Yani onları gerçekten silmemelisin. Kaydet yanlış cevaplar için siler.
sblundy

2
Evet, biliyorum - koroya vaaz veriyorsun, aynı şeyi başkalarına da söyledim. Gerçek olduğunu bildiğimiz bu şeyleri yaşamak genellikle göründüğünden daha zordur. :)
Jason Bunting

0

Herkes jQuery ile çalışan bir çözüm arıyor, ayarlanmış wiki kodu (orijinal jQuery tatili).

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

Evet, jQuery 'hasOwnProperty' denetimi yapmayı başaramaz ve böylece numaralandırır getNameve devrilir.
nicodemus13

0

Lodash'ın birçok isMethods'ı vardır, bu nedenle Lodash kullanıyorsanız, bunun gibi bir karışım yararlı olabilir:

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

Aşağıdaki gibi çalışan "tanımlama" adı verilen bir yöntem ekler:

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

Dalgıç: http://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN


0

Tamam, millet yavaş yavaş birkaç yıldır lol bunun için tüm yöntemi yakalamak yapıyorum! İşin püf noktası:

  1. Sınıf oluşturmak için bir mekanizmaya sahip olun.
  2. Yerel oluşturucular tarafından oluşturulan / oluşturulan tüm kullanıcı sınıfları, ilkel değerleri ve değerleri kontrol etmek için bir mekanizmaya sahip olun.
  3. Yukarıdaki işlevselliğin kod / uygulama / kütüphane / vb.

Bir örnek (veya sorunla nasıl başa çıktığımı görmek için) github'daki şu koda bakın: https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js ve ara:

classOf =, classOfIs =ve veya defineSubClass =(ters tırnaklar olmadan (`)).

Gördüğünüz classOfgibi, ilkel, kullanıcı tanımlı bir sınıf, yerel bir kurucu, Null, NaN, vb. Kullanılarak oluşturulan bir değer olup olmadığına bakılmaksızın, bana her zaman sınıfları / kurucular tür adını vermeye zorlamak için bazı mekanizmalar var . Her bir javascript değeri için classOfişlevden benzersiz tip adı alacak . Buna ek olarak, gerçek kurucularısjl.classOfIs bir değer türünü de kontrol etmenin yanı sıra, tür adını da aktarabiliyorum! Yani mesela:

`` // Lütfen uzun ad alanlarını affedin! Onları bir süre kullanana kadar etkisi hakkında hiçbir fikrim yoktu (haha emiyorlar)

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

`

Yukarıda belirtilen kurulumu nasıl kullandığım hakkında daha fazla bilgi edinmek istiyorsanız repoya bir göz atın: https://github.com/elycruz/sjljs

Ayrıca konuyla ilgili içeriğe sahip kitaplar: - Stoyan Stefanov'un "JavaScript Patterns". - "Javascript - Kesin Kılavuz." David Flanagan tarafından. - ve diğerleri .. (web'de arama).

Ayrıca burada bahsettiğim özellikleri hızlı bir şekilde test edebilirsiniz : - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (ayrıca url'deki 0.5.18 yolu github kaynaklarına sahiptir orada eksi_modüller ve benzeri).

Mutlu Kodlama!


0

Oldukça Basit!

  • JS'de herhangi bir şey türünü almak için en sevdiğim yöntem
function getType(entity){
    var x = Object.prototype.toString.call(entity)
    return x.split(" ")[1].split(']')[0].toLowerCase()
}
  • JS'de bir şey türünü kontrol etmek için en sevdiğim yöntem
function checkType(entity, type){
    return getType(entity) === type
}

-1

Kullanın class.name. Bu aynı zamanda çalışır function.name.

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

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

Soru, açıkça classdeğil, örnek diyor .
qwertzguy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.