Misalkan aku punya variabel, yang didefinisikan sebagai berikut:
var a = function() {/* Statements */};
Saya ingin fungsi yang memeriksa apakah tipe dari variabel adalah fungsi-suka. yaitu :
function foo(v) {if (v is function type?) {/* do something */}};
foo(a);
Bagaimana saya bisa memeriksa apakah variabel a
adalah dari jenis Fungsi
dalam cara yang dijelaskan di atas?
Yakin menggarisbawahi's cara yang lebih efisien, tapi cara terbaik untuk memeriksa, ketika efisiensi isn't masalah, yang tertulis pada garis bawah's halaman dihubungkan oleh @Paul Rosania.
Terinspirasi oleh garis bawah, final isFunction fungsi adalah sebagai berikut:
function isFunction(functionToCheck) {
return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}
Underscore.js menggunakan lebih rumit tapi sangat performant tes:
_.isFunction = function(obj) {
return !!(obj && obj.constructor && obj.call && obj.apply);
};
Lihat: http://jsperf.com/alternative-isfunction-implementations
EDIT: diperbarui tes menunjukkan bahwa typeof mungkin akan lebih cepat, lihat http://jsperf.com/alternative-isfunction-implementations/4
Ada beberapa cara agar saya akan meringkas mereka semua
Paling performant (tidak ada perbandingan string) dan elegan solusi - operator instanceof telah didukung dalam browser untuk waktu yang sangat lama, jadi don't khawatir - itu akan bekerja di IE 6.fungsi foo(v) {if (v instanceof Fungsi) {/ lakukan sesuatu /} };
kelemahan darifungsi foo(v) {if (typeof v === "fungsi") {/ lakukan sesuatu /} };
jenis
adalah bahwa hal itu lebih rentan untuk diam kegagalan, buruk, jadi jika anda memiliki kesalahan ketik (misalnya "finction") - dalam hal ini `jika` hanya akan kembali palsu dan anda tidak't tahu anda memiliki kesalahan sampai kemudian dalam kode anda
Ini memiliki keuntungan lebih dari solusi #1 atau #2, tetapi adalah jauh lebih mudah dibaca. Sebuah versi perbaikan dari hal ini adalahfungsi isFunction(functionToCheck) { var getType = {}; kembali functionToCheck && getType.toString.panggilan(functionToCheck) === '[objek Fungsi]'; }
fungsi isFunction(x) { kembali Objek.prototipe.toString.panggilan(x) == '[objek Fungsi]'; }
tapi masih banyak yang kurang semantik dari solusi #1
jQuery (sudah ditinggalkan sejak versi 3.3) Referensi
$.isFunction(functionName);
AngularJS Referensi
angular.isFunction(value);
Lodash Referensi
_.isFunction(value);
Menggarisbawahi Referensi
_.isFunction(object);
Node.js tak berlaku lagi sejak v4.0.0 Referensi
var util = require('util');
util.isFunction(object);
Mencoba instanceof
operator: tampaknya bahwa semua fungsi mewarisi dari Fungsi
kelas:
// Test data
var f1 = function () { alert("test"); }
var o1 = { Name: "Object_1" };
F_est = function () { };
var o2 = new F_est();
// Results
alert(f1 instanceof Function); // true
alert(o1 instanceof Function); // false
alert(o2 instanceof Function); // false
Sesuatu dengan lebih banyak dukungan browser dan juga mencakup async fungsi bisa:
const isFunction = value => value && (Object.prototype.toString.call(value) === "[object Function]" || "function" === typeof value || value instanceof Function);
dan kemudian mengujinya seperti:
isFunction(isFunction); //true
isFunction(function(){}); //true
isFunction(()=> {}); //true
isFunction(()=> {return 1}); //true
isFunction(async function asyncFunction(){}); //true
isFunction(Array); //true
isFunction(Date); //true
isFunction(Object); //true
isFunction(Number); //true
isFunction(String); //true
isFunction(Symbol); //true
isFunction({}); //false
isFunction([]); //false
isFunction("function"); //false
isFunction(true); //false
isFunction(1); //false
isFunction("Alireza Dezfoolian"); //false
Bagi mereka yang's tertarik pada gaya fungsional, atau terlihat lebih ekspresif pendekatan untuk memanfaatkan dalam meta pemrograman (seperti jenis pemeriksaan), itu bisa menjadi menarik untuk melihat Ramda perpustakaan untuk menyelesaikan tugas tersebut.
Berikutnya kode hanya berisi murni dan pointfree fungsi:
const R = require('ramda');
const isPrototypeEquals = R.pipe(Object.getPrototypeOf, R.equals);
const equalsSyncFunction = isPrototypeEquals(() => {});
const isSyncFunction = R.pipe(Object.getPrototypeOf, equalsSyncFunction);
Sebagai ES2017, async
fungsi yang tersedia, sehingga kita dapat memeriksa terhadap mereka serta:
const equalsAsyncFunction = isPrototypeEquals(async () => {});
const isAsyncFunction = R.pipe(Object.getPrototypeOf, equalsAsyncFunction);
Dan kemudian menggabungkan mereka bersama-sama:
const isFunction = R.either(isSyncFunction, isAsyncFunction);
Tentu saja, fungsi harus dilindungi terhadap null
dan undefined
nilai-nilai, sehingga untuk membuat "aman":
const safeIsFunction = R.unless(R.isNil, isFunction);
Dan, lengkap cuplikan singkatnya:
const R = require('ramda');
const isPrototypeEquals = R.pipe(Object.getPrototypeOf, R.equals);
const equalsSyncFunction = isPrototypeEquals(() => {});
const equalsAsyncFunction = isPrototypeEquals(async () => {});
const isSyncFunction = R.pipe(Object.getPrototypeOf, equalsSyncFunction);
const isAsyncFunction = R.pipe(Object.getPrototypeOf, equalsAsyncFunction);
const isFunction = R.either(isSyncFunction, isAsyncFunction);
const safeIsFunction = R.unless(R.isNil, isFunction);
// ---
console.log(safeIsFunction( function () {} ));
console.log(safeIsFunction( () => {} ));
console.log(safeIsFunction( (async () => {}) ));
console.log(safeIsFunction( new class {} ));
console.log(safeIsFunction( {} ));
console.log(safeIsFunction( [] ));
console.log(safeIsFunction( 'a' ));
console.log(safeIsFunction( 1 ));
console.log(safeIsFunction( null ));
console.log(safeIsFunction( undefined ));
Namun, catatan larutan ini bisa menunjukkan kinerja kurang dari pilihan lain yang tersedia karena penggunaan yang luas dari tingkat tinggi fungsi.
Jika anda menggunakan Lodash anda dapat melakukannya dengan _.isFunction.
_.isFunction(function(){});
// => true
_.isFunction(/abc/);
// => false
_.isFunction(true);
// => false
_.isFunction(null);
// => false
Metode ini mengembalikan true
jika nilai adalah fungsi, yang lain palsu
.
Di bawah ini tampaknya bekerja untuk saya juga (diuji dari node.js
):
var isFunction = function(o) {
return Function.prototype.isPrototypeOf(o);
};
console.log(isFunction(function(){})); // true
console.log(isFunction({})); // false
Saya menemukan bahwa ketika pengujian browser asli fungsi di IE8, menggunakan toString
, instanceof
, dan jenis
tidak bekerja. Berikut ini adalah metode yang bekerja dengan baik di IE8 (sejauh yang saya tahu):
function isFn(f){
return !!(f && f.call && f.apply);
}
//Returns true in IE7/8
isFn(document.getElementById);
Atau, anda dapat memeriksa untuk fungsi asli menggunakan:
"getElementById" in document
Meskipun, saya telah membaca di suatu tempat bahwa ini tidak akan selalu bekerja di IE7 dan di bawah ini.
Saya pikir anda hanya dapat menentukan bendera pada prototipe Fungsi dan memeriksa jika misalnya anda ingin menguji warisan yang
menetapkan bendera:
Function.prototype.isFunction = true;
dan kemudian memeriksa jika ada
var foo = function(){};
foo.isFunction; // will return true
The downside adalah bahwa lain prototipe dapat menentukan bendera yang sama dan kemudian's tidak berharga, tetapi jika anda memiliki kontrol penuh atas termasuk modul ini adalah cara termudah
Solusi seperti beberapa jawaban sebelumnya telah menunjukkan adalah dengan menggunakan typeof. berikut adalah potongan kode Di NodeJs,
function startx() {
console.log("startx function called.");
}
var fct= {};
fct["/startx"] = startx;
if (typeof fct[/startx] === 'function') { //check if function then execute it
fct[/startx]();
}