Javascript değişkeni türünü almanın daha iyi bir yolu var mı?


260

JS'de bir değişkenin türünü almanın daha iyi bir yolu var mı typeof? Yaptığınızda iyi çalışır:

> typeof 1
"number"
> typeof "hello"
"string"

Ama denediğinizde işe yaramaz:

> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"

Biliyorum instanceof, ama bu önceden türü bilmenizi gerektirir.

> [1,2] instanceof Array
true
> r instanceof RegExp
true

Daha iyi bir yol var mı?


1
Bilginize, typeof new RegExp(/./); // "function"Chrome'daki sorun Chrome 14'te giderilmiş gibi görünüyor.
user113716 12:11


Uyarı: JS'nizi küçültüyorsanız ve daktilo sınıfları gibi 'özel nesneler' kullanıyorsanız, aşağıdaki yanıtlardan bazıları n, beklenen orijinal ad yerine gizlenmiş işlev adını verir. Örneğin , beklenen tam ad yerine constructor.namesize verebilirn
Simon_Weaver

Yanıtlar:


221

Angus Croll kısa süre önce bu konuda ilginç bir blog yazısı yazdı -

http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

Çeşitli yöntemlerin artılarını ve eksilerini geçer ve daha sonra yeni bir yöntem 'toType' tanımlar -

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

3
Burada ilginç yan not - bu fonksiyona bir "host" nesnesinin geçtiği yerde kırılabilir. ActiveXObjectÖrneğin, Internet Explorer örnekleri.
Andy E

Kendi nesne türünüzü (prototypal mirası) oluşturduysanız, "nesne" den daha spesifik bir değer döndürmesini nasıl sağlayabilirsiniz? Bu da burada bir sorun olarak gündeme geldi , ama asla ele alınmadı.
EleventyOne

1
Tür adınız aşağıdakileri içeriyorsa: veya _ bu normal match(/\s([a-z,_,:,A-Z]+)/)
ifadeyi

6
Normal ifadenin, benzer şeyler için de sayılar içermesi gerekir Uint8Array. Bunun yerine, match(/\s([^\]]+)/)herhangi bir şeyi ele alması gereken daha genel olanı düşünün .
Lily Finley

2
Bunun \wyerine operatör kelimesini kullanmanızı öneririm …
kaiser 0

51

Kullanmayı deneyebilirsiniz constructor.name.

[].constructor.name
new RegExp().constructor.name

Her şey JavaScript'te olduğu gibi, birisi sonunda her zaman bunun bir şekilde kötü olduğunu gösterecektir, bu yüzden burada bunu oldukça iyi kapsayan bir cevaba bağlantı var .

Bir alternatif kullanmaktır Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)

10
nameECMAScript'in bir uzantısıdır ve tüm tarayıcılarda çalışmaz.
Andy E

16
Javascript'te yapılan her şeyin bir şekilde kötü olduğuna dair şüphe doğrulandığından dolayı oy verin.
liljoshu

1
KÖTÜ: Kodunuzu küçültüyorsanız constructor.name, büyük olasılıkla nbeklediğiniz nesne adı gibi bir şey olabilir . Öyleyse buna dikkat edin - özellikle sadece üretimde küçülüyorsanız.
Simon_Weaver

nullve undefinedne yazık ki bir kurucu yok.
Andrew Grimm

JavaScript'in kendisi kötülüktür. Ve aptalca. Bu sorunun iyi bir cevabı olmadığı gerçeği bunun canlı kanıtıdır.
user2173353

38

Oldukça iyi bir tür yakalama işlevi YUI3 tarafından kullanılan işlevdir :

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

Bu, javascript tarafından sağlanan ilkellerin çoğunu yakalar, ancak TYPESnesneyi değiştirerek her zaman daha fazlasını ekleyebilirsiniz . Not typeof HTMLElementCollectionSafari bildirir içinde function, ancak tipi (HTMLElementCollection) döndürecektirobject


31

Aşağıdaki işlevi yararlı bulabilirsiniz:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

Veya ES7'de (daha fazla iyileştirme olursa yorum yapın)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

Sonuçlar:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

Beni haberdar ettiğiniz için teşekkürler @johnrees: hata, söz, jeneratör


Bunun için teşekkürler. Aynı zamanda tarih nesneleri için de çalışır:typeOf(new Date())
James Irwin

Ah, unutmuştum - teşekkürler, şimdi dahil.
Vix

1
VetypeOf(Promise.resolve())//promise typeOf(function *() {})//generatorfunction
johnrees

Bu cevabı daktiloda çalışmak için alamıyorum. Hata verir:[ts] Cannot redeclare block-scoped variable 'toString'
DauleDK

TypeScript hakkında emin değilim. ES7 sürümünü denediniz mi? toString'in açıkça bildirilmemesinin nedeni olabilir mi?
Vix

15

Ayrıca ipr101'den küçük bir örnek değiştirebiliriz

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

ve olarak ara

"aaa".toType(); // 'string'

6
Çocukları hatırlayın, JavaScript temel nesnelerini değiştirmek uyumluluğa ve diğer garip sorunlara yol açabilir. Bunu hem kütüphanelerde hem de daha büyük projelerde az miktarda kullanmaya çalışın!
Alexander Craggs

9

bir satır fonksiyonu:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

bu aynı sonucu verir jQuery.type()


3

Object.prototype.toStringHerhangi bir nesneye başvurabilirsiniz :

var toString = Object.prototype.toString;

console.log(toString.call([]));
//-> [object Array]

console.log(toString.call(/reg/g));
//-> [object RegExp]

console.log(toString.call({}));
//-> [object Object]

Bu, IE hariç tüm tarayıcılarda iyi çalışır - bunu başka bir pencereden elde edilen bir değişkene çağırdığınızda tükürecektir [object Object].


1
@Xeon Bence IE'ye karşı olan nefret biraz fazla. IE9, öncekilerden çok daha iyi bir tarayıcıdır.
Aillyn

4
@pessimopoppotamus ama tarayıcılarını IE9'a güncelleyecek kimse IE kullanmıyor.
Alex Turpin

1
IE 9 doğru yönde atılmış bir adım, IE 10 oldukça iyi görünüyor. Bu arada, bahsettiğim hata IE 9'da bir gerileme oldu - IE 8'de düzelttiler.
Andy E

3

Benim 2 ¢! Gerçekten, uzun cevaplar listesine rağmen, bunu buraya atmamın nedeninin bir kısmı, biraz daha all in onetip bir çözüm sağlamak ve gelecekte daha fazlasını içerecek şekilde nasıl genişleteceğiniz konusunda geri bildirim almaktır real types.

Aşağıdaki çözümle, yukarıda belirtildiği gibi, burada bulunan birkaç çözümü birleştirdim ve mevcutsa , jQuery tanımlı nesnenin değerini döndürmek için bir düzeltmejQuery ekledim . Yöntemi yerel Object prototipine de ekliyorum. Bu tür uzantılara müdahale edebileceğinden, bunun genellikle tabu olduğunu biliyorum, ama bunu bırakıyorum . Bunu yapmaktan hoşlanmıyorsanız, temel işlevi istediğiniz yere kopyalayın ve tüm değişkenlerini aktarmak için bir argüman parametresiyle değiştirin (argümanlar [0] gibi).user bewarethis

;(function() {  //  Object.realType
    function realType(toLower) {
        var r = typeof this;
        try {
            if (window.hasOwnProperty('jQuery') && this.constructor && this.constructor == jQuery) r = 'jQuery';
            else r = this.constructor && this.constructor.name ? this.constructor.name : Object.prototype.toString.call(this).slice(8, -1);
        }
        catch(e) { if (this['toString']) r = this.toString().slice(8, -1); }
        return !toLower ? r : r.toLowerCase();
    }
    Object['defineProperty'] && !Object.prototype.hasOwnProperty('realType')
        ? Object.defineProperty(Object.prototype, 'realType', { value: realType }) : Object.prototype['realType'] = realType;
})();

O zaman bu şekilde kolayca kullanın:

obj.realType()  //  would return 'Object'
obj.realType(true)  //  would return 'object'

Not: 1 argüman iletilebilir. Eğer bool ise true, geri dönüş her zaman küçük harf olur .

Daha fazla örnek:

true.realType();                            //  "Boolean"
var a = 4; a.realType();                    //  "Number"
$('div:first').realType();                   // "jQuery"
document.createElement('div').realType()    //  "HTMLDivElement"

Başka bir kitaplıkla (Moo, Proto, Yui, Dojo, vb.) Bir nesnenin ne zaman oluşturulduğunu tanımlamak gibi yararlı olabilecek bir şey varsa, lütfen bunu yorumlamaktan veya düzenlemek ve daha fazla olmaya devam etmek için çekinmeyin doğru ve kesin. VEYA GitHubbunun için yaptım ve bana bildirin. Ayrıca orada bir cdn min dosyasına hızlı bir bağlantı bulacaksınız.


2
function getType(obj) {
    if(obj && obj.constructor && obj.constructor.name) {
        return obj.constructor.name;
    }
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

Ön testlerimde, bu oldukça iyi çalışıyor. İlk vaka, "yeni" ile oluşturulan herhangi bir nesnenin adını yazdıracak ve 2. vaka, diğer her şeyi yakalayacaktır.

Ben kullanıyorum (8, -1)ben sonucu her zaman birlikte başlayacak varsayarak olduğum için [objectve sona ]ama her senaryoda doğru emin değilim.


2

İçin kontrol etmektir - Burada en evrensel çözüm tahmin undefinedve nullilk sonra sadece ara constructor.name.toLowerCase().

const getType = v =>
  v === undefined
    ? 'undefined'
    : v === null
      ? 'null'
      : v.constructor.name.toLowerCase();




console.log(getType(undefined)); // 'undefined'
console.log(getType(null)); // 'null'
console.log(getType('')); // 'string'
console.log(getType([])); // 'array'
console.log(getType({})); // 'object'
console.log(getType(new Set())); // `set'
console.log(getType(Promise.resolve())); // `promise'
console.log(getType(new Map())); // `map'

Bildiğim kadarıyla - .constructor.nameher zaman dize değeri içerir. Undefined / null için işlev tarafından döndürülen uygun dizelerimiz var.
Arsenowitch

Teşekkürler - yorumlarımı
siliyorum

Yana constructorbir kalıtsal bir özelliktir, nesneler için bu sonları ile oluşturulan Object.create(null). Düzeltmek için yeterince basit, ama ne denir? "[nesne null]"?
traktor53

0

typeof koşul, değişken türünü kontrol etmek için kullanılır, eğer if-else koşulunda değişken türünü kontrol ediyorsanız, ör.

if(typeof Varaible_Name "undefined")
{

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