programing tip

변수가 함수 유형인지 확인

itbloger 2020. 9. 29. 07:23
반응형

변수가 함수 유형인지 확인


다음과 같이 정의 된 변수가 있다고 가정합니다.

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

변수의 유형이 함수와 같은지 확인하는 함수를 원합니다. 즉 :

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

변수 aFunction위에서 정의한 방식 으로 유형 인지 어떻게 확인할 수 있습니까?


확실히 밑줄의 방법이 더 효율적이지만 효율성이 문제가되지 않을 때 확인하는 가장 좋은 방법은 @Paul Rosania가 링크 한 밑줄 페이지에 적혀 있습니다.

밑줄에서 영감을 얻은 최종 isFunction 함수는 다음과 같습니다.

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

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

Underscore.js 는 더 정교하지만 성능이 뛰어난 테스트를 사용합니다.

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

참조 : http://jsperf.com/alternative-isfunction-implementations

편집 : 업데이트 된 테스트는 typeof가 더 빠를 수 있음을 시사합니다. http://jsperf.com/alternative-isfunction-implementations/4 참조


여러 가지 방법이 있으므로 모두 요약하겠습니다

  1. 가장 좋은 방법은 다음과 같습니다.
    
    function foo (v) {if (v instanceof Function) {/ * do something * /}};
    
    
    가장 성능이 뛰어나고 (문자열 비교 없음) 우아한 솔루션-instanceof 연산자는 브라우저에서 매우 오랫동안 지원되었으므로 걱정하지 마십시오. IE 6에서 작동합니다.
  2. 다음으로 가장 좋은 방법은 다음과 같습니다.
    
    function foo (v) {if (typeof v === "function") {/ * 뭔가를하세요 * /}};
    
    
    의 단점은 typeof자동 실패에 취약하다는 것입니다. 따라서 오타가있는 경우 (예 : "finction")-이 경우`if`는 false를 반환하고 나중에 오류가 있음을 알 수 없습니다. 당신의 코드
  3. 차선책은 다음과 같습니다.
    
    function isFunction (functionToCheck) {
        var getType = {};
        return functionToCheck && getType.toString.call (functionToCheck) === '[객체 함수]';
    }
    
    
    이것은 솔루션 # 1 또는 # 2에 비해 이점이 없지만 훨씬 읽기 어렵습니다. 이것의 개선 된 버전은
    
    function isFunction (x) {
        return Object.prototype.toString.call (x) == '[객체 함수]';
    }
    
    
    그러나 여전히 솔루션 # 1보다 의미가 훨씬 적습니다.

jQuery (버전 3.3부터 사용되지 않음) 참조

$.isFunction(functionName);

AngularJS 참조

angular.isFunction(value);

Lodash 참조

_.isFunction(value);

밑줄 참조

_.isFunction(object); 

Node.js는 v4.0.0 부터 사용되지 않음 참조

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

@grandecomplex : 솔루션에 상당한 양의 장황함이 있습니다. 다음과 같이 작성하면 훨씬 더 명확해질 것입니다.

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

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


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

다른 간단한 방법 :

var fn = function () {}
if (fn.constructor === Function) {
  // true
} else {
  // false
}

더 많은 브라우저를 지원하고 비동기 기능을 포함하는 것은 다음과 같습니다.

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

and then test it like:

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

For those who's interested in functional style, or looks for more expressive approach to utilize in meta programming (such as type checking), it could be interesting to see Ramda library to accomplish such task.

Next code contains only pure and pointfree functions:

const R = require('ramda');

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

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

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

As of ES2017, async functions are available, so we can check against them as well:

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

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

And then combine them together:

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

Of course, function should be protected against null and undefined values, so to make it "safe":

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

And, complete snippet to sum up:

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

However, note the this solution could show less performance than other available options due to extensive usage of higher-order functions.


If you use Lodash you can do it with _.isFunction.

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

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

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

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

This method returns true if value is a function, else false.


I found that when testing native browser functions in IE8, using toString, instanceof, and typeof did not work. Here is a method that works fine in IE8 (as far as I know):

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

Alternatively, you can check for native functions using:

"getElementById" in document

Though, I have read somewhere that this will not always work in IE7 and below.


The below seems to work for me as well (tested from node.js):

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

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

Since node v0.11 you can use the standard util function :

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

I think you can just define a flag on the Function prototype and check if the instance you want to test inherited that

define a flag:

Function.prototype.isFunction = true; 

and then check if it exist

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

The downside is that another prototype can define the same flag and then it's worthless, but if you have full control over the included modules it is the easiest way


you should use typeOf operator in js.

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

The solution as some previous answers has shown is to use typeof. the following is a code snippet In 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]();
  }

참고URL : https://stackoverflow.com/questions/5999998/check-if-a-variable-is-of-function-type

반응형