JS nesnesinin türünü kontrol etmenin en doğru yolu?


138

typeofOperatör gerçekten bir nesnenin gerçek türünü bulmak için bize yardımcı olmuyor.

Ben zaten aşağıdaki kodu gördüm:

Object.prototype.toString.apply(t)  

Soru:

Öyle mi çoğu nesnenin türünü denetlemek doğru yolu?





3
En doğru yol ... tipi test etmemek. Neden bu tiplere ihtiyacınız var?
hugomg

Object.prototype.toString.call / Object.prototype.toString.apply
xgqfrms

Yanıtlar:


191

JavaScript belirtimi, bir nesnenin sınıfını belirlemek için tam olarak uygun bir yol sağlar:

Object.prototype.toString.call(t);

http://bonsaiden.github.com/JavaScript-Garden/#types


5
Belirli bir tür arıyorsanız, muhtemelen şu satırlarda bir şeyler yapmak istersiniz: Object.prototype.toString.call(new FormData()) === "[object FormData]"bu doğru olur. Ayrıca kullanabilirsiniz slice(8, -1)dönmek FormDatayerine[object FormData]
Chris Marisic

4
Kullanarak arasında herhangi bir fark var mı Object.prototypeve {}?
GetFree

3
belki bu yıl içinde değişti, ama etmiştir Object.prototype.toString.call(new MyCustomObject())döner [object Object]oysa new MyCustomObject() instanceOf MyCustomObject returns trueki ben (Krom 54.0.2840.99 m) ne istediğini
Maslow

@Maslow, gündeme getirdiğin aynı sorunla karşılaştım. Bazı belgeleri çevrimiçi olarak inceledikten sonra, kullandım new MyCustomObject().constructor === MyCustomObject.
solstice333

3
Bu kodu neden daha uygun bir yöntemle sarmadıkları veya ek bir operatörün buna derlemesine izin vermedikleri sorusunu akla getiriyor. Sadece haberci olduğunu biliyorum, ama açıkçası bu korkunç.
Andrew S

60

Object.prototype.toStringiyi bir yoldur, fakat performansı kötü.

http://jsperf.com/check-js-type

js tipi performansını kontrol et

typeofBazı temel problemleri (String, Number, Boolean ...) çözmek için kullanın ve kullanınObject.prototype.toString (Dizi, Tarih, RegExp gibi) kompleks bir şey çözmek için.

ve bu benim çözümüm:

var type = (function(global) {
    var cache = {};
    return function(obj) {
        var key;
        return obj === null ? 'null' // null
            : obj === global ? 'global' // window in browser or global in nodejs
            : (key = typeof obj) !== 'object' ? key // basic: string, boolean, number, undefined, function
            : obj.nodeType ? 'object' // DOM element
            : cache[key = ({}).toString.call(obj)] // cached. date, regexp, error, object, array, math
            || (cache[key] = key.slice(8, -1).toLowerCase()); // get XXXX from [object XXXX], and cache it
    };
}(this));

olarak kullan:

type(function(){}); // -> "function"
type([1, 2, 3]); // -> "array"
type(new Date()); // -> "date"
type({}); // -> "object"

JsPerf'deki bu test pek doğru değil. Bu testler eşit değildir (aynı şeyi test etmek). Örneğin, typeof [], "object" değerini döndürür, typeof {} de, bir nesne Array ve diğeri bir Object Object olsa bile "object" değerini döndürür. Bu testle ilgili başka birçok sorun var ... jsPerf'e bakarken testlerin Elmaları Elmalar ile karşılaştırdığına dikkat edin.
kmatheny

Sizin typefonksiyonu iyidir, ama diğer bazı kıyasla yok nasıl bakmak typefonksiyonları. http://jsperf.com/code-type-test-a-test
Progo

18
Bu performans metrikleri sağduyulu olmalıdır. Elbette, prototip.toString, bir büyüklük sırasına göre diğerlerinden daha yavaştır, ancak şeylerin büyük şemasında, çağrı başına ortalama birkaç yüz nanosaniye sürer . Bu çağrı çok sık yürütülen kritik bir yolda kullanılmadığı sürece, bu muhtemelen zararsızdır. Daha doğrusu bir mikrosaniye daha hızlı bitirir kodu yerine düz ileri kodu olurdu.
David

({}).toString.call(obj)Object.prototype.toString jsperf.com/object-check-test77'den
timaschew

Güzel çözüm. Ben senin fonksiyonunu benim lib içine ödünç :)
Dong Nguyen

19

Kabul edilen cevap doğrudur, ancak inşa ettiğim çoğu projede bu küçük yardımcı programı tanımlamayı seviyorum.

var types = {
   'get': function(prop) {
      return Object.prototype.toString.call(prop);
   },
   'null': '[object Null]',
   'object': '[object Object]',
   'array': '[object Array]',
   'string': '[object String]',
   'boolean': '[object Boolean]',
   'number': '[object Number]',
   'date': '[object Date]',
}

Bunun gibi kullanılır:

if(types.get(prop) == types.number) {

}

Açısal kullanıyorsanız, temiz enjekte bile edebilirsiniz:

angular.constant('types', types);

11
var o = ...
var proto =  Object.getPrototypeOf(o);
proto === SomeThing;

Nesnenin sahip olmasını beklediğiniz prototip üzerinde bir tanıtıcı tutun, ardından nesneyle karşılaştırın.

Örneğin

var o = "someString";
var proto =  Object.getPrototypeOf(o);
proto === String.prototype; // true

Bu söylemekten daha iyi / farklı o instanceof String; //truemı?
Jamie Treworgy

@jamietre çünkü "foo" instanceof Stringtatili
Raynos

Tamam, bu yüzden "typeof (o) === 'object' && o instanceof SomeObject". Dizeleri test etmek kolaydır. Ne için test ettiğinizi önceden bilmek zorunda kalmadan temel sorunu çözmeden ekstra bir iş gibi görünüyor.
Jamie Treworgy

Maalesef kod snippet'inin bir anlamı yok, ancak dizeleri test ediyorsanız ne demek istediğimi bildiğinizi düşünüyorum, typeof(x)==='string'bunun yerine kullanın.
Jamie Treworgy

BTW, geri döndüğünde Object.getPrototypeOf(true)başarısız olur . (true).constructorBoolean
katspaugh

5

Burada gösterilen çözümlerin çoğunun aşırı mühendislikten muzdarip olduğunu iddia ediyorum. Muhtemelen bir değerin tür [object Object]olup olmadığını kontrol etmenin en basit yolu, değerinin .constructorözelliğine karşı kontrol etmektir :

function isObject (a) { return a != null && a.constructor === Object; }

veya ok fonksiyonları ile daha da kısa:

const isObject = a => a != null && a.constructor === Object;

a != nullTek geçmek çünkü parçası gereklidir nullveyaundefined ve bunlardan birinden bir yapıcı özelliği ayıklayamazsınız.

Şu yolla oluşturulan herhangi bir nesne ile çalışır:

  • Objectinşaatçı
  • değişmezleri {}

Bunun bir başka düzgün özelliği, özel sınıflar için doğru raporları verebilmesidir Symbol.toStringTag. Örneğin:

class MimicObject {
  get [Symbol.toStringTag]() {
    return 'Object';
  }
}

Buradaki sorun Object.prototype.toString, bir örneğini çağırırken yanlış raporun [object Object]döndürülmesidir:

let fakeObj = new MimicObject();
Object.prototype.toString.call(fakeObj); // -> [object Object]

Ancak yapıcıya karşı kontrol etmek doğru bir sonuç verir:

let fakeObj = new MimicObject();
fakeObj.constructor === Object; // -> false

4

Bir nesnenin GERÇEK türünü (yerel Nesne veya DataType adı (Dize, Tarih, Sayı, ..etc gibi) VE bir nesnenin GERÇEK türünü (özel olanlar bile dahil) bulmanın en iyi yolu; nesne prototipi yapıcısının name özelliği:

Yerel Tip Ex1:

var string1 = "Test";
console.log(string1.__proto__.constructor.name);

görüntüler:

String

ex2:

var array1 = [];
console.log(array1.__proto__.constructor.name);

görüntüler:

Array

Özel Sınıflar:

function CustomClass(){
  console.log("Custom Class Object Created!");
}
var custom1 = new CustomClass();

console.log(custom1.__proto__.constructor.name);

görüntüler:

CustomClass

Nesne ya nullda ise bu başarısız olur undefined.
Julian Knight

2

Eski bir soru biliyorum. Dönüştürmeniz gerekmez. Bu işleve bakın:

function getType( oObj )
{
    if( typeof oObj === "object" )
    {
          return ( oObj === null )?'Null':
          // Check if it is an alien object, for example created as {world:'hello'}
          ( typeof oObj.constructor !== "function" )?'Object':
          // else return object name (string)
          oObj.constructor.name;              
    }   

    // Test simple types (not constructed types)
    return ( typeof oObj === "boolean")?'Boolean':
           ( typeof oObj === "number")?'Number':
           ( typeof oObj === "string")?'String':
           ( typeof oObj === "function")?'Function':false;

}; 

Örnekler:

function MyObject() {}; // Just for example

console.log( getType( new String( "hello ") )); // String
console.log( getType( new Function() );         // Function
console.log( getType( {} ));                    // Object
console.log( getType( [] ));                    // Array
console.log( getType( new MyObject() ));        // MyObject

var bTest = false,
    uAny,  // Is undefined
    fTest  function() {};

 // Non constructed standard types
console.log( getType( bTest ));                 // Boolean
console.log( getType( 1.00 ));                  // Number
console.log( getType( 2000 ));                  // Number
console.log( getType( 'hello' ));               // String
console.log( getType( "hello" ));               // String
console.log( getType( fTest ));                 // Function
console.log( getType( uAny ));                  // false, cannot produce
                                                // a string

Düşük maliyetli ve basit.


falseTest nesnesinin nullveyaundefined
Julian Knight

veya trueveyafalse
Julian Knight

@JulianKnight false, null veya undefined'de tamamdır, yararlı bir şey değildir. Peki amaç ne?
Codebeat

örneğiniz tutarsız veriler döndürüyor. Bazı sonuçlar veri türüdür ve diğerleri değerdir false. Bu soruya cevap vermeye nasıl yardımcı olur?
Julian Knight

1
@JulianKnight Değişikliklere bakın, istediğiniz şey bu mu? Sonuç olarak undefined veya "undefined" tercih ediyorsanız, isterseniz son yanlış değeri değiştirebilirsiniz.
Codebeat

0

Yukarıdaki doğru cevaplardan esinlenen küçük bir tür kontrol yardımcı programını bir araya getirdim:

thetypeof = function(name) {
        let obj = {};
        obj.object = 'object Object'
        obj.array = 'object Array'
        obj.string = 'object String'
        obj.boolean = 'object Boolean'
        obj.number = 'object Number'
        obj.type = Object.prototype.toString.call(name).slice(1, -1)
        obj.name = Object.prototype.toString.call(name).slice(8, -1)
        obj.is = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type === obj[ofType])? true: false
        }
        obj.isnt = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type !== obj[ofType])? true: false
        }
        obj.error = (ofType) => {
            throw new TypeError(`The type of ${name} is ${obj.name}: `
            +`it should be of type ${ofType}`)
        }
        return obj;
    };

misal:

if (thetypeof(prop).isnt('String')) thetypeof(prop).error('String')
if (thetypeof(prop).is('Number')) // do something

nullVeya undefinedveya trueveya olan nesneler için çalışmıyor gibi görünüyorfalse
Julian Knight
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.