විචල්‍යයක් ශ්‍රිත වර්ගයට අයත් දැයි පරීක්ෂා කරන්න


939

මට කිසියම් විචල්‍යයක් ඇතැයි සිතමු, එය පහත පරිදි අර්ථ දැක්වේ:

var a = function() {/* Statements */};

මට අවශ්‍ය වන්නේ විචල්‍යයේ වර්ගය ශ්‍රිතයට සමාන දැයි පරීක්ෂා කරන ශ්‍රිතයකි. එනම්:

function foo(v) {if (v is function type?) {/* do something */}};
foo(a);

ඉහත අර්ථ දක්වා ඇති ආකාරයට විචල්‍යය aවර්ග තිබේදැයි පරීක්ෂා කරන්නේ Functionකෙසේද?


Answers:


391

අවතක්සේරු කිරීමේ ක්‍රමය වඩා කාර්යක්ෂම බව සහතිකයි, නමුත් කාර්යක්ෂමතාව ගැටළුවක් නොවන විට පරීක්ෂා කිරීමට හොඳම ක්‍රමය @ පෝල් රොසානියා විසින් සම්බන්ධ කර ඇති යටි ඉරි පිටුවේ ලියා ඇත.

අවධාරනය මගින් දේවානුභාවයෙන්, අවසාන isFunction ශ්‍රිතය පහත පරිදි වේ:

function isFunction(functionToCheck) {
 return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}

1
මේ පිළිබඳව වඩාත් පුළුල් පර්යේෂණ සිදු කළ අයෙකු සිටිය හැකි නමුත් සරල “ප්‍රති result ල සත්‍යාපනය” සමඟ jsperf හි 4 වන සංශෝධනයේ ප්‍රති results ල දෙස බලන්න . isFunctionAඅනෙක් ක්‍රම සමඟ සසඳන විට ක්‍රියාත්මක කිරීමේ වෙනසක් පෙන්වයි.
ජොයෙල් පුර

26
යාවත්කාලීන කරන ලද කාර්ය සාධන පරීක්ෂණ සමඟ ඔබගේ බ්‍රව්සරය අනුව විශාල වේග වෙනසක් ඇති බව පෙනේ. ක්‍රෝම් හි typeof(obj) === 'function'මෙතෙක් වේගවත්ම බව පෙනේ; කෙසේ වෙතත්, ෆයර්ෆොක්ස් obj instanceof Functionහි පැහැදිලි ජයග්‍රාහකයා වේ.
ජස්ටින් වර්කෙන්ටින්

7
කොටස සම්බන්ධයෙන්: typeof භාවිතා කළ යුත්තේ විචල්‍යයන් හෝ ගුණාංග නිර්වචනය කර ඇත්දැයි පරීක්ෂා කිරීම සඳහා පමණි. දී javascript.info/tutorial/type-detection තුළ typeof සඳහා හොඳ භාවිතය නඩුව හරියටම ප්රතිවිරුද්ධ බව, කොටස සහ පහත කතෘ රාජ්යයන් එක්
කොන්රාඩ් Madej

12
ඇලෙක්ස්, මට කුතුහලයක් ඇති වන්නේ ඇයි? එහි නමෙන් ඇඟවෙන්නේ එහි අරමුණ යමක් තිබේද යන්න පරීක්ෂා කිරීම මිස එය පවතින්නේද යන්නයි. වර්ග පරීක්ෂා කිරීම සඳහා එය භාවිතා කිරීමේදී තාක්ෂණික ගැටළු හෝ ගැටලු තිබේද, නැතහොත් එය මනාපයක්ද? අවවාද තිබේ නම් ඒවා ලැයිස්තුගත කිරීම හොඳය, එවිට අනෙක් අයට ඒවා ඉක්මවා යාම වළක්වා ගත හැකිය.
jinglesthula

21
අසාධාරණ ලෙස සංකීර්ණ වූ විසඳුම
ඩැනියෙල් ගර්මොෂ්කා

1790
if (typeof v === "function") {
    // do something
}

45
වගේ දේවල් කීපයක් සදහා බලන්න typeof Object, typeof Dateසහ typeof Stringසියලු ආපසු වන 'function'ද.
ඩේව් වෝඩ්

373
Ave ඩේව්, ඒවා ක්‍රියාකාරී බැවින් ගැටලුව කුමක්දැයි මට විශ්වාස නැත.
මැතිව් ක්‍රම්ලි

6
වෙනස if (v instanceOf Function)කුමක්ද?
mquandalle

10
qumquandalle ඔබ වෙනත් ලේඛනයකින් instanceofපැමිණි ශ්‍රිතයක් පරීක්ෂා කරන්නේ නම් හැර විශාල වෙනසක් නැත (iframe , සමහර විට). කාර්ය සාධනය වෙනස් වේ.
rvighne

10
පිළිගත් පිළිතුර මෙන් නොව මෙය අසින්ක් ශ්‍රිත සඳහාද ක්‍රියා කරයි. සඳහා asyncfunctionToCheck, getType.toString.call(functionToCheck)==='[object AsyncFunction]'කොහේදtypeof asyncfunctionToCheck === 'function'
TDreama

135

Underscore.js වඩාත් සවිස්තරාත්මක නමුත් ඉහළ කාර්ය සාධනයක් සහිත පරීක්ෂණයක් භාවිතා කරයි:

_.isFunction = function(obj) {
  return !!(obj && obj.constructor && obj.call && obj.apply);
};

බලන්න: http://jsperf.com/alternative-isfunction-implementations

සංස්කරණය කරන්න: යාවත්කාලීන කරන ලද පරීක්ෂණ මඟින් යතුරු ලියනය වේගවත් විය හැකි බව බලන්න, http://jsperf.com/alternative-isfunction-implementations/4 බලන්න


මෙම ප්‍රවේශය භාවිතා කිරීමට විශේෂ හේතුවක් typofතිබේද?
sv_in

1
අන්ඩර්ස්කෝර් අනුවාදය බොහෝ බ්‍රව්සර් වල වඩා වේගවත් ය. බලන්න: jsperf.com/alternative-isfunction-implementations
පෝල්

14
මම විශ්වාස කරනවා අවධාරනය කරන්න, සරල නමුත් බලවත්. එයින් කියැවෙන්නේ, මෙම ගුණාංගයන් සහිත වස්තුවක් මගින් මෙම ක්‍රියාවට නැංවිය හැකි බව සඳහන් කිරීම වටී.
studgeek

3
APaulRosania අද පෙර මෙම කාර්ය සාධන පරීක්ෂණ වලට බාධා කළ අතර ඒවා සත්‍යාපනය සහ තවත් පරීක්ෂණ දත්ත 4 වන සංශෝධනය ලෙස යාවත්කාලීන කරන ලදි - කරුණාකර එය බ්‍රව්සර් පරීක්ෂණ ආවරණය වැඩි කිරීමට ක්‍රියාත්මක කරන්න. එය තත්පරයට මෙහෙයුම් මන්දගාමී වේ (බොහෝ පරීක්ෂණ හේතුවෙන්), නමුත් එය එක් ක්‍රියාත්මක කිරීමේ වෙනසක් ද පෙන්වයි (ඔබේ ජාවාස්ක්‍රිප්ට් කොන්සෝලය විවෘත කර පිටුව නැවත පූරණය කරන්න, ලොග් වූ දෝෂ පණිවිඩ තිබිය හැක). සටහන: සංශෝධනය 3 එකතු කිරීම isFunctionD (පමණක් පදනම් කරගෙන typeof == "function") - එය අන්ඩර්ස්කෝර් හි "වේගවත්" අනුවාදයට වඩා වේගවත් බව පෙනේ .
ජොයෙල් පුර

6
මෙම පිළිතුර දැන් ටිකක් නොමඟ යවන සුළු ය, Underscore.js දැන් එහි විකල්ප ක්‍රියාත්මක කිරීම් පිළිබඳ පරීක්ෂණයේ ඉහත සඳහන් 4 වන සංශෝධනය නොව 12 වන සංශෝධනයෙහිisFunction() ඇත. එය දැනට ඩැන්ඩියන් යෝජනා කළ දෙයට ඉතා ආසන්න දෙයක් භාවිතා කරයි .
ජොනතන් යුනිස්

115

ක්‍රම කිහිපයක් තිබේ, එබැවින් මම ඒවා සියල්ලම සාරාංශ කරමි

  1. හොඳම ක්‍රමය නම්:
    ශ්‍රිතය foo (v) {if (v instanceof function) {/ * යමක් කරන්න * /}};
    
    
    බොහෝ කාර්ය සාධනය (නූල් සැසඳීමක් නැත) සහ අලංකාර විසඳුම - නිදර්ශන ක්‍රියාකරුට බ්‍රව්සර්වල දීර් time කාලයක් තිස්සේ සහය ලබා දී ඇත, එබැවින් කරදර නොවන්න - එය IE 6 හි ක්‍රියා කරනු ඇත.
  2. ඊළඟ හොඳම ක්‍රමය නම්:
    ශ්‍රිතය foo (v) {if (typeof v === "function") {/ * යමක් කරන්න * /}};
    
    
    හි අවාසිය typeof නම් එය නිහ silent අසාර්ථකත්වයට ගොදුරු වීමයි, නරකයි, එබැවින් ඔබට අක්ෂර වින්‍යාසයක් තිබේ නම් (උදා: "ෆින්ෂන්") - මේ අවස්ථාවේ දී `if` වැරදියට නැවත පැමිණෙනු ඇති අතර පසුව ඔබට දෝෂයක් ඇති බව ඔබ නොදනී. ඔබේ කේතය
  3. ඊළඟ හොඳම ක්‍රමය නම්:
    ශ්‍රිතය isFunction (functionToCheck) {
        var getType = {};
        return functionToCheck && getType.toString.call (functionToCheck) === '[වස්තු ක්‍රියාකාරිත්වය]';
    }
    
    
    මෙය විසඳුම # 1 හෝ # 2 ට වඩා වාසියක් නැති නමුත් කියවිය හැකි ප්‍රමාණයට වඩා අඩුය. මෙහි වැඩිදියුණු කළ අනුවාදයකි
    ශ්‍රිතය isFunction (x) {
        ආපසු Object.prototype.toString.call (x) == '[වස්තු ශ්‍රිතය]';
    }
    
    
    නමුත් තවමත් විසඳුම # 1 ට වඩා අඩු අර්ථකථනයක් ඇත

12
ශ්‍රිතයක් වෙනත් රාමු සන්දර්භයකට යොමු කළ විට පළමු විසඳුම අසමත් වේ. උදාහරණයක් ලෙස, iframe එකකින් top.Function !== Function. නිසැකවම, දෙවැන්න භාවිතා කරන්න ("ශ්‍රිතයේ" අක්ෂර වින්‍යාසය නිදොස් කිරීමේදී නිවැරදි කරනු ඇත, බලාපොරොත්තු සහගතව).
මැක්ස්ආර්ට්

1
යතුරු ලියනය පිළිබඳ ඔබේ අදහස සම්බන්ධයෙන්: මෙම යතුරු ලියනය ඇති ඕනෑම කේතයක් ඉක්මනින් අසමත් වීමට ඉඩ ඇත / යතුරු ලියනය මත පදනම් වූ වෙනත් දෝෂ වලට වඩා පැහැදිලිව පෙනෙන්නට නැත. typeof === "ශ්‍රිතය" යනු පිරිසිදුම විසඳුමයි. මීට අමතරව, ඔබ භාවිතා කරන ඔබේ “හොඳම” විසඳුම instanceofරාමු හරහා චෙක්පතක් වැනි බහු ගෝලීයයන් සැලකිල්ලට නොගන්නා අතර ව්‍යාජ නිෂේධනීය දෑ ආපසු ලබා දිය හැකිය.
brainkim


56

@grandecomplex: ඔබේ විසඳුමට සෑහෙන තරම් වාචික බවක් ඇත. මේ ආකාරයට ලියා ඇත්නම් එය වඩාත් පැහැදිලි වනු ඇත:

function isFunction(x) {
  return Object.prototype.toString.call(x) == '[object Function]';
}

ඔබ උනන්දුවක් දක්වන වෙනත් ජාවාස්ක්‍රිප්ට් වර්ග සඳහා Object.prototype.toString.call ප්‍රයෝජනවත් වේ. ඔබට එය ඉතා බලවත් වන ශුන්‍ය හෝ නිර්වචනය නොකළද පරීක්ෂා කළ හැකිය.
ජේසන් ෆොග්ලියා

49

var foo = function(){};
if (typeof foo === "function") {
  alert("is function")
}


1
... සහ (() => (typeof obj === 'function') && doSomething())තවමත් වේගවත්ම විකල්පයයි.
darcher

37

instanceofක්රියාකරු උත්සාහ කරන්න : සියලු කාර්යයන් Functionපන්තියෙන් උරුම වන බව පෙනේ :

// 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

24

වඩා බ්‍රව්සර් සහය ඇති සහ අසින්ක් ශ්‍රිත ඇතුළත් යමක් විය හැකිය:

const isFunction = value => value && (Object.prototype.toString.call(value) === "[object Function]" || "function" === typeof value || value instanceof Function);

ඉන්පසු එය මෙසේ පරීක්ෂා කරන්න:

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


9

ක්‍රියාකාරී ශෛලිය ගැන උනන්දුවක් දක්වන හෝ මෙටා ක්‍රමලේඛනය සඳහා භාවිතා කිරීමට වඩාත් ප්‍රකාශන ප්‍රවේශයක් සොයන අයට (වර්ගය පරීක්ෂා කිරීම වැනි), රාම්ඩා දැකීම සිත්ගන්නාසුළු විය හැකිය එවැනි කාර්යයක් ඉටු පුස්තකාලය .

ඊළඟ කේතයේ අඩංගු වන්නේ පිරිසිදු හා ලක්ෂ්‍ය රහිත කාර්යයන් පමණි:

const R = require('ramda');

const isPrototypeEquals = R.pipe(Object.getPrototypeOf, R.equals);

const equalsSyncFunction = isPrototypeEquals(() => {});

const isSyncFunction = R.pipe(Object.getPrototypeOf, equalsSyncFunction);

ES2017 වන විට, asyncකාර්යයන් තිබේ, එබැවින් අපට ඒවාට එරෙහිවද පරීක්ෂා කළ හැකිය:

const equalsAsyncFunction = isPrototypeEquals(async () => {});

const isAsyncFunction = R.pipe(Object.getPrototypeOf, equalsAsyncFunction);

ඉන්පසු ඒවා එකට ඒකාබද්ධ කරන්න:

const isFunction = R.either(isSyncFunction, isAsyncFunction);

ඇත්ත වශයෙන්ම, ක්‍රියාකාරීත්වය nullසහ undefinedඅගයන්ගෙන් ආරක්ෂා විය යුතුය , එබැවින් එය "ආරක්ෂිත" බවට පත් කිරීම:

const safeIsFunction = R.unless(R.isNil, isFunction);

සාරාංශගත කිරීම සඳහා සම්පූර්ණ ස්නිපටය:

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 ));

කෙසේ වෙතත්, ඉහළ ඇණවුම් කාර්යයන් පුළුල් ලෙස භාවිතා කිරීම හේතුවෙන් මෙම විසඳුම වෙනත් පවතින විකල්පයන්ට වඩා අඩු කාර්ය සාධනයක් පෙන්විය හැකි බව සලකන්න.


7

ඔබ ලොඩාෂ් භාවිතා කරන්නේ නම් ඔබට එය _.isFunction සමඟ කළ හැකිය .

_.isFunction(function(){});
// => true

_.isFunction(/abc/);
// => false

_.isFunction(true);
// => false

_.isFunction(null);
// => false

trueඅගය ශ්‍රිතයක් නම් මෙම ක්‍රමය නැවත පැමිණේ false.


4

මම භාවිතා 8 යනු ස්වදේශික බ්රවුසරය කාර්යයන් පරීක්ෂා කරන විට බව සොයා toString, instanceofසහ typeofවැඩ කටයුතු කළේ නැත. IE8 හි හොඳින් ක්‍රියාත්මක වන ක්‍රමයක් මෙන්න (මා දන්නා පරිදි):

function isFn(f){
    return !!(f && f.call && f.apply);
}
//Returns true in IE7/8
isFn(document.getElementById);

විකල්පයක් ලෙස, ඔබට මෙය භාවිතා කර ස්වදේශීය කාර්යයන් පරීක්ෂා කළ හැකිය:

"getElementById" in document

කෙසේ වෙතත්, මෙය සෑම විටම IE7 සහ ඊට පහළින් ක්‍රියාත්මක නොවන බව මම කොතැනක හෝ කියවා ඇත්තෙමි.


4

පහත දැක්වෙන්නේ මටද වැඩ කරන බව පෙනේ (පරීක්ෂා කර ඇත node.js):

var isFunction = function(o) {
     return Function.prototype.isPrototypeOf(o);
};

console.log(isFunction(function(){})); // true
console.log(isFunction({})); // false

4

මම හිතන්නේ ඔබට ක්‍රියාකාරී මූලාකෘතියේ ධජයක් අර්ථ දැක්විය හැකි අතර ඔබට එය පරීක්ෂා කිරීමට අවශ්‍ය අවස්ථාව එය උරුම වී ඇත්දැයි පරීක්ෂා කරන්න

ධජයක් අර්ථ දක්වන්න:

Function.prototype.isFunction = true; 

ඉන්පසු එය තිබේදැයි පරීක්ෂා කරන්න

var foo = function(){};
foo.isFunction; // will return true

අවාසිය නම් වෙනත් මූලාකෘතියකට එකම ධජය නිර්වචනය කළ හැකි අතර එය නිෂ් less ල ය, නමුත් ඇතුළත් කළ මොඩියුලයන් පිළිබඳ පූර්ණ පාලනයක් ඔබට තිබේ නම් එය පහසුම ක්‍රමයයි


Foo නිර්වචනය නොකළහොත් එය දෝෂය සමඟ අසමත් වනු ඇත. ඔබ ස්වදේශීය මූලාකෘතිය වෙනස් කරන බව සඳහන් නොකිරීම මුළුමනින්ම වැරදිය.
කමිල් ඔර්චොව්ස්කි

3

V0.11 නෝඩ් සිට ඔබට සම්මත උපයෝගීතා ශ්‍රිතය භාවිතා කළ හැකිය:

var util = require('util');
util.isFunction('foo');

2
util.isFunction අතහැර දමා ඇත
kehers

2

ඔබ js හි typeOfක්‍රියාකරු භාවිතා කළ යුතුය .

var a=function(){
    alert("fun a");
}
alert(typeof a);// alerts "function"

0

මීට පෙර සමහර පිළිතුරු පෙන්වා ඇති පරිදි විසඳුම ටයිප් ඕෆ් භාවිතා කිරීමයි. පහත දැක්වෙන්නේ කේත ස්නිපටයක් වන 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]();
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.