Saya ingin tahu cara mendaftar semua metode yang tersedia untuk objek seperti misalnya:
alert(show_all_methods(Math));
Ini harus mencetak:
abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Saya ingin tahu cara mendaftar semua metode yang tersedia untuk objek seperti misalnya:
alert(show_all_methods(Math));
Ini harus mencetak:
abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, …
Jawaban:
Anda bisa menggunakan Object.getOwnPropertyNames()
untuk mendapatkan semua properti yang dimiliki oleh suatu objek, apakah dapat dihitung atau tidak. Sebagai contoh:
console.log(Object.getOwnPropertyNames(Math));
//-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ]
Anda dapat menggunakan filter()
hanya untuk mendapatkan metode:
console.log(Object.getOwnPropertyNames(Math).filter(function (p) {
return typeof Math[p] === 'function';
}));
//-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ]
Di browser ES3 (IE 8 dan lebih rendah), properti objek bawaan tidak dapat dihitung. Objek suka window
dan document
tidak built-in, mereka ditentukan oleh browser dan kemungkinan besar dihitung berdasarkan desain.
Dari ECMA-262 Edition 3 :
Objek Global
Ada objek global unik (15.1), yang dibuat sebelum kontrol memasuki konteks eksekusi. Awalnya objek global memiliki sifat-sifat berikut:• Objek bawaan seperti Matematika, String, Tanggal, parseInt, dll. Ini memiliki atribut {DontEnum} .
• Properti tambahan yang ditentukan host. Ini mungkin termasuk properti yang nilainya adalah objek global itu sendiri; misalnya, dalam model objek dokumen HTML properti jendela objek global adalah objek global itu sendiri.Ketika kontrol memasuki konteks eksekusi, dan ketika kode ECMAScript dieksekusi, properti tambahan dapat ditambahkan ke objek global dan properti awal dapat diubah.
Saya harus menunjukkan bahwa ini berarti objek-objek itu bukan properti enumerable dari objek Global. Jika Anda melihat melalui sisa dokumen spesifikasi, Anda akan melihat sebagian besar properti bawaan dan metode objek ini memiliki { DontEnum }
atribut yang ditetapkan padanya.
Pembaruan: sesama pengguna SO, CMS, membawa bug IE tentang{ DontEnum }
perhatian saya.
Alih-alih memeriksa atribut DontEnum, [Microsoft] JScript akan melewati properti apa pun di objek mana pun di mana ada properti dengan nama yang sama dalam rantai prototipe objek yang memiliki atribut DontEnum.
Singkatnya, waspadalah saat menamai properti objek Anda. Jika ada properti prototipe atau metode bawaan dengan nama yang sama maka IE akan melewatinya saat menggunakan for...in
loop.
Object.getOwnPropertyNames()
, yang akan mengembalikan bahkan properti dan metode yang tidak dapat dihitung.
Object.getOwnPropertyNames(Array.prototype)
?
Ini tidak mungkin dengan ES3 karena properti memiliki DontEnum
atribut internal yang mencegah kami menghitung properti ini. ES5, di sisi lain, menyediakan deskriptor properti untuk mengontrol kemampuan enumerasi properti sehingga properti yang ditentukan pengguna dan asli dapat menggunakan antarmuka yang sama dan menikmati kemampuan yang sama, yang mencakup kemampuan untuk melihat properti non-enumerable secara terprogram.
The getOwnPropertyNames
fungsi dapat digunakan untuk menghitung atas semua sifat-sifat berlalu dalam objek, termasuk mereka yang non-enumerable. Kemudian pemeriksaan sederhana typeof
dapat digunakan untuk menyaring non-fungsi. Sayangnya, Chrome adalah satu-satunya browser yang berfungsi saat ini.
function getAllMethods(object) {
return Object.getOwnPropertyNames(object).filter(function(property) {
return typeof object[property] == 'function';
});
}
console.log(getAllMethods(Math));
log ["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]
tanpa urutan tertentu.
var methods = [];
for (var m in obj) {
if (typeof obj[m] == "function") {
methods.push(m);
}
}
alert(methods.join(","));
Dengan cara ini, Anda akan mendapatkan semua metode yang dapat Anda panggil obj
. Ini termasuk metode yang "diwariskan" dari prototipe-nya (seperti getMethods()
di java). Jika Anda hanya ingin melihat metode-metode yang didefinisikan secara langsung oleh obj
Anda dapat memeriksa dengan hasOwnProperty
:
var methods = [];
for (var m in obj) {
if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) {
methods.push(m);
}
}
alert(methods.join(","));
document
atau window
saya mendapatkan lebih banyak keberuntungan. Terus terang itu agak tidak terduga, saya tidak tahu mengapa itu tidak berhasil untuk Matematika dll.
document
dan window
objek dengan properti enumerable yang disediakan oleh browser, mereka bukan bagian dari runtime scripting. Objek asli adalah dan jelas properti tidak dapat dihitung.
Sebagian besar dukungan browser modern console.dir(obj)
, yang akan mengembalikan semua properti dari objek yang diwarisi melalui konstruktornya. Lihat dokumentasi Mozilla untuk info lebih lanjut dan dukungan browser saat ini.
console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object
Jawaban lain di sini berfungsi untuk sesuatu seperti Matematika, yang merupakan objek statis. Tetapi mereka tidak bekerja untuk instance objek, seperti kencan. Saya menemukan yang berikut ini berfungsi:
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/
Ini tidak akan berfungsi untuk sesuatu seperti pertanyaan awal (Matematika), jadi pilih solusi Anda berdasarkan kebutuhan Anda. Saya memposting ini di sini karena Google mengirim saya ke pertanyaan ini, tetapi saya ingin tahu bagaimana melakukan ini untuk contoh objek.
Jawaban singkatnya adalah Anda tidak bisa karena Math
dan Date
(dari atas kepala saya, saya yakin ada orang lain) bukan objek normal. Untuk melihatnya, buat skrip pengujian sederhana:
<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>
Anda melihatnya menyajikan sebagai objek dengan cara yang sama dengan yang dilakukan dokumen secara keseluruhan, tetapi ketika Anda benar-benar mencoba dan melihat dalam objek itu, Anda melihat bahwa itu adalah kode asli dan sesuatu yang tidak diekspos dengan cara yang sama untuk penghitungan.
Math
memiliki metode statis di mana Anda dapat memanggil langsung suka Math.abs()
sementara Date
memiliki metode statis suka Date.now()
dan juga metode contoh di mana Anda perlu membuat instance baru terlebih dahulu var time = new Date()
untuk memanggil 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);
Tentu saja Anda perlu memfilter kunci yang diperoleh untuk metode statis untuk mendapatkan nama metode yang sebenarnya, karena Anda juga bisa mendapatkanlength, name
itu bukan fungsi pada daftar.
Tetapi bagaimana jika kita ingin mendapatkan semua metode yang tersedia dari kelas yang memperluas kelas lain?
Tentu saja Anda harus memindai melalui akar prototipe seperti menggunakan __proto__
. Untuk menghemat waktu Anda, Anda dapat menggunakan skrip di bawah ini untuk mendapatkan metode statis dan contoh metode mendalam.
// 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));
Jika Anda ingin mendapatkan metode dari instance yang dibuat, jangan lupa untuk melewatkannya constructor
.
Saya percaya ada alasan historis sederhana mengapa Anda tidak dapat menyebutkan metode objek bawaan seperti Array misalnya. Inilah alasannya:
Metode adalah properti dari prototipe-objek, misalnya Object.prototype. Itu berarti bahwa semua instance Object akan mewarisi metode-metode itu. Itu sebabnya Anda bisa menggunakan metode itu pada objek apa pun. Katakan .toString () misalnya.
Jadi, JIKA metode dihitung, dan saya akan beralih mengatakan {a: 123} dengan: "for (masukkan {a: 123}) {...}" apa yang akan terjadi? Berapa kali loop itu dieksekusi?
Itu akan diulang sekali untuk satu kunci 'a' dalam contoh kita. TETAPI JUGA satu kali untuk setiap properti enumerable Object.prototype. Jadi jika metode enumerable (secara default), maka setiap loop atas objek apa pun akan mengulang semua metode yang diwarisi.
Object.getOwnPropertyNames(Array.prototype)
misalnya