Bir nesnenin tüm yöntemlerini nasıl görüntüleyebilirim?


249

Nasıl örneğin bir nesne için kullanılabilir tüm yöntemleri listelemek bilmek istiyorum:

 alert(show_all_methods(Math));

Bunun yazdırılması gerekir:

abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, 

Yanıtlar:


298

Object.getOwnPropertyNames()Numaralandırılabilir olsun veya olmasın, bir nesneye ait tüm özellikleri almak için kullanabilirsiniz . Örneğin:

console.log(Object.getOwnPropertyNames(Math));
//-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ]

Daha sonra filter()yalnızca yöntemleri elde etmek için kullanabilirsiniz :

console.log(Object.getOwnPropertyNames(Math).filter(function (p) {
    return typeof Math[p] === 'function';
}));
//-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ]

ES3 tarayıcılarda (IE 8 ve altı), yerleşik nesnelerin özellikleri numaralandırılamaz. Nesneler gibi windowve documentyerleşik değildir, tarayıcı tarafından tanımlanır ve büyük olasılıkla tasarımla numaralandırılabilir.

Gönderen ECMA-262 sürüm 3 :

Genel Nesne
Denetim herhangi bir yürütme içeriğine girmeden önce oluşturulan benzersiz bir genel nesne (15.1) vardır. Başlangıçta global nesne aşağıdaki özelliklere sahiptir:

• Math, String, Date, parseInt, vb. Gibi yerleşik nesneler. Bunların {DontEnum} öznitelikleri vardır .
• Ek ana bilgisayar tanımlı özellikler. Bu, değeri global nesnenin kendisi olan bir özelliği içerebilir; örneğin, HTML belgesi nesne modelinde global nesnenin window özelliği global nesnenin kendisidir.

Denetim yürütme bağlamına girdiğinde ve ECMAScript kodu yürütüldükçe, genel nesneye ek özellikler eklenebilir ve ilk özellikler değiştirilebilir.

Bunun, bu nesnelerin Global nesnenin numaralandırılabilir özellikleri olmadığı anlamına geldiğini belirtmeliyim. Teknik özellik belgesinin geri kalanına bakarsanız, bu nesnelerin yerleşik özelliklerinin ve yöntemlerinin çoğunun üzerinde { DontEnum }öznitelik ayarlanmış olduğunu görürsünüz .


Güncelleme: bir SO kullanıcısı, CMS, dikkatimi çeken bir IE hatası{ DontEnum } getirdi .

DontEnum özniteliğini kontrol etmek yerine, [Microsoft] JScript, nesnenin prototip zincirinde DontEnum özniteliğine sahip aynı adlı bir özelliğin bulunduğu herhangi bir nesnede herhangi bir özelliği atlar.

Kısacası, nesne özelliklerinizi adlandırırken dikkatli olun. Aynı ada sahip yerleşik bir prototip özelliği veya yöntemi varsa, for...indöngü kullanılırken IE üstünden atlar .


Andy E, bunu belirttiğin için teşekkürler. Açıkçası ben bunun farkında değildi ve ben bu kazma ve burada söz çaba için teşekkür ederiz. Tekrar teşekkürler :)
Roland Bouman

@Roland: Endişelenme. Belki biraz üzücüdür, ancak Belgelerim klasöründe sakladığım özellikler var, bu yüzden gerçekten çok kazma gerekli değil!
Andy E

Yeni JS uygulamalarındaki tüm yöntemlerin bir listesini almanın bir yolu yok mu? Node.js ve V8 gibi mi? Sahte nesne çerçeveleri gibi eskiden yaptığımız gibi yansıma ve içgözlemli nesneleri nasıl yaparız? Ben sadece JS unuttum sanıyordum, ama sanırım işler yıllar içinde değişti :)
d11wtq

2
@ d11wtq, ES5 uygulamaları ile, Object.getOwnPropertyNames()numaralandırılamayan özellikler ve yöntemler bile döndürecek şekilde çağırabilirsiniz .
Andy E

tüm nesneler kendi prototiplerinden miras aldığından, böyle bir şey yapmak daha iyi olmaz mıydı Object.getOwnPropertyNames(Array.prototype) ?
lfender6445

71

ES3 ile bu mümkün değildir, çünkü özellikler DontEnumbu özellikleri numaralandırmamızı engelleyen dahili bir özniteliğe sahiptir. Öte yandan ES5, özelliklerin numaralandırma yeteneklerini denetlemek için özellik tanımlayıcıları sağlar, böylece kullanıcı tanımlı ve yerel özellikler aynı arabirimi kullanabilir ve aynı özelliklerin keyfini çıkarabilir, bu da numaralandırılamayan özellikleri programlı olarak görebilmeyi içerir.

getOwnPropertyNamesFonksiyonu olmayan numaralandırılabilir olanlar da dahil olmak üzere, bir nesne geçirilen tüm özelliklerini numaralandırmak için kullanılabilir. Ardından, typeofişlevsizlikleri filtrelemek için basit bir kontrol kullanılabilir. Maalesef, Chrome şu anda üzerinde çalıştığı tek tarayıcıdır.

function getAllMethods(object) {
    return Object.getOwnPropertyNames(object).filter(function(property) {
        return typeof object[property] == 'function';
    });
}

console.log(getAllMethods(Math));

kaydeder ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]özel bir sırada.


ES5 şeyler için +1. IE9'un ES5'i tam olarak destekleyeceği için bu şeyleri bilmek iyidir.
Andy E

1
@Andy - Microsoft IE9'u çok ciddiye alıyor ki bu beni mutlu ediyor :)
Anurag

console.log (işlev (a) {dönüş Object.getOwnPropertyNames (a) .filter (işlev (b) {dönüş "işlev" == [b]} türünde)} (Matematik)); Teşekkür ederim!
19h

1
Bilet getOwnPropertyNames. Nashorn'da bile çalışıyor. Sadece Java nesnesinin yöntemlerinin adlarını değiştirdiler ve Object.getOwnPropertyNames (Java)
cayhorstmann

60
var methods = [];
for (var m in obj) {
    if (typeof obj[m] == "function") {
        methods.push(m);
    }
}
alert(methods.join(","));

Bu şekilde, arayabileceğiniz tüm yöntemleri elde edersiniz obj. Bu, prototipinden "miras aldığı" yöntemleri içerir ( getMethods()java gibi ). Yalnızca doğrudan tarafından tanımlanan bu yöntemleri görmek objistiyorsanız, şunları kontrol edebilirsiniz hasOwnProperty:

var methods = [];
for (var m in obj) {        
    if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) {
        methods.push(m);
    }
}
alert(methods.join(","));

evet, ben de fark ediyorum. Gibi bir şey kullandığımda documentveya windowdaha fazla şans olsun. Açıkçası biraz beklenmedik, neden Matematik vb. İçin işe yaramaz bilmiyorum
Roland Bouman

4
@Roland: Çünkü var documentve windowtarayıcı tarafından sağlanan enumerable özelliklere sahip nesneler, onlar komut dosyası çalışma zamanı parçası değiliz. Yerel nesnelerdir ve açıkçası özellikler numaralandırılamaz.
Andy E

1
Herhangi bir E, bunun açık olduğunu kabul etmiyorum Demek istediğim, onları numaralandıramayacağımız için belli. Ancak bu yerleşiklerin neden özelliklerinin numaralandırılmasını engellemesi gerektiği mantığını görmüyorum. Sadece merak ediyorum, bu yerleşiklerin numaralandırılabilir özelliklere sahip olmaması gerektiğini söyleyen standardın bir kısmı var mı?
Roland Bouman

@Roland: Üzgünüm, demek istediğim bir for-in ile gelmedikleri için numaralandırılmadıkları açık. Spesifikasyondan bir teklif için aşağıdaki cevabımı görün.
Andy E

@Mic: Math, özellikleri numaralandırılamayan yerleşik bir nesnedir.
Andy E

31

console.dir(obj)Yapıcı aracılığıyla devraldığı bir nesnenin tüm özelliklerini döndürecek en modern tarayıcı desteği . Daha fazla bilgi ve güncel tarayıcı desteği için Mozilla'nın belgelerine bakın .

console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object

4

Buradaki diğer cevaplar, statik bir nesne olan Math gibi bir şey için işe yarar. Ancak tarih gibi bir nesnenin örneği için çalışmazlar . Çalışmak için aşağıdakileri buldum:

function getMethods(o) {
  return Object.getOwnPropertyNames(Object.getPrototypeOf(o))
    .filter(m => 'function' === typeof o[m])
}
//example: getMethods(new Date()):  [ 'getFullYear', 'setMonth', ... ]

https://jsfiddle.net/3xrsead0/

Bu alışkanlık böylece ihtiyaçlarınıza göre çözüm almak, asıl soruya (Matematik) böyle bir şey için çalışır. Bunu burada gönderiyorum çünkü Google beni bu soruya gönderdi ama bunu nesnelerin örnekleri için nasıl yapacağımı bilmek istiyordum.


3

Kısa cevap, yapamayacağınızdır Mathve Date(başımın üstünden, başkaları olduğundan eminim) normal nesneler değildir. Bunu görmek için basit bir test komut dosyası oluşturun:

<html>
  <body>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
      $(function() {
        alert("Math: " + Math);
        alert("Math: " + Math.sqrt);
        alert("Date: " + Date);
        alert("Array: " + Array);
        alert("jQuery: " + jQuery);
        alert("Document: " + document);
        alert("Document: " + document.ready);
      });
    </script>
  </body>
</html>

Belgenin genel olarak yaptığı gibi bir nesne olarak göründüğünü görüyorsunuz, ancak o nesneyi gerçekten denediğinizde ve gördüğünüzde, yerel kodun ve numaralandırma için aynı şekilde gösterilmeyen bir şeyin olduğunu görüyorsunuz.


1

MathEğer gibi doğrudan arayabilecek statik yöntem vardır Math.abs()iken Datestatik gibi yöntem vardır Date.now()öncelikle yeni bir örneğini oluşturmak için gereken ve aynı zamanda örnek yöntemi var time = new Date()çağrısına time.getHours().

// The instance method of Date can be found on `Date.prototype` so you can just call:
var keys = Object.getOwnPropertyNames(Date.prototype);

// And for the static method
var keys = Object.getOwnPropertyNames(Date);

// But if the instance already created you need to
// pass its constructor
var time = new Date();
var staticKeys = Object.getOwnPropertyNames(time.constructor);
var instanceKeys = Object.getOwnPropertyNames(time.constructor.prototype);

Tabii ki , gerçek yöntem adlarını almak için statik yöntem için elde edilen anahtarları filtrelemeniz gerekecektir , çünkü aynı zamanda length, namelistede bir işlev değildir.

Peki, başka bir sınıfı genişleten sınıftan tüm mevcut yöntemleri elde etmek istiyorsak nasıl olur?
Tabii ki kullanmak gibi prototipin kökünü taramanız gerekecektir __proto__. Zamandan tasarruf etmek için statik yöntemi ve derin yöntem örneğini almak için aşağıdaki komut dosyasını kullanabilirsiniz.

// var keys = new Set();
function getStaticMethods(keys, clas){
    var keys2 = Object.getOwnPropertyNames(clas);

    for(var i = 0; i < keys2.length; i++){
        if(clas[keys2[i]].constructor === Function)
            keys.add(keys2[i]);
    }
}

function getPrototypeMethods(keys, clas){
    if(clas.prototype === void 0)
        return;

    var keys2 = Object.getOwnPropertyNames(clas.prototype);
    for (var i = keys2.length - 1; i >= 0; i--) {
        if(keys2[i] !== 'constructor')
            keys.add(keys2[i]);
    }

    var deep = Object.getPrototypeOf(clas);
    if(deep.prototype !== void 0)
        getPrototypeMethods(keys, deep);
}

// ====== Usage example ======
// To avoid duplicate on deeper prototype we use `Set`
var keys = new Set();
getStaticMethods(keys, Date);
getPrototypeMethods(keys, Date);

console.log(Array.from(keys));

Oluşturulan örnekten yöntemler elde etmek istiyorsanız, bunu geçmeyi unutmayın constructor.


0

Örneğin Array gibi yerleşik nesnelerin yöntemlerini sıralayamamanızın basit bir tarihsel nedeni olduğuna inanıyorum. İşte nedeni:

Yöntemler prototip-nesnenin özellikleridir, örneğin Object.prototype. Bu, tüm Object-instance'ların bu yöntemleri miras alacağı anlamına gelir. Bu yüzden bu yöntemleri herhangi bir nesnede kullanabilirsiniz. Örneğin .toString () deyin.

Yani EĞER yöntemleri numaralandırılabilir ve ben tekrar {a: 123} demek ile tekrar ediyorum: ile (anahtar {a: 123}) {...} "ne olurdu? Bu döngü kaç kez yürütülür?

Örneğimizdeki tek anahtar 'a' için bir kez yinelenecektir. AMA AYRICA Nesne.prototip her numaralandırılabilir özelliği için bir kez . Bu nedenle, yöntemler numaralandırılabilir olsaydı (varsayılan olarak), herhangi bir nesne üzerindeki herhangi bir döngü, tüm devralınan yöntemlerinin üzerinde de döngü yapardı.


1
ilkeller genellikle bir prototipten miras aldığından, bu Object.getOwnPropertyNames(Array.prototype)örneğin mümkündür
lfender6445

Ne demek yöntemler Object.prototype özellikleri vardır. ? Nesne durumunda her özellik Object.prototype özellikleridir
debugmode
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.