변수가 함수 타입인지 확인


904

다음과 같이 정의 된 변수가 있다고 가정하십시오.

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

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

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

변수 aFunction위에서 정의한 방식 인지 확인하려면 어떻게 해야합니까?


2
여기이 확인이 가장 일반적인 방법에 대한 벤치 마크 jsben.ch/#/e5Ogr을
EscapeNetscape

답변:


380

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

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

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

1
이 문제에 대해 더 광범위한 연구를 한 사람이있을 수 있지만 간단한 "결과 검증"으로 jsperf 개정 4의 결과를 살펴 보는 사람이있을 수 있습니다 . isFunctionA다른 방법과 비교하여 구현 차이를 보여줍니다.
Joel Purra

24
함께 업데이트 된 성능 테스트 브라우저에 따라 큰 속도 차이가있을 것 같습니다. Chrome typeof(obj) === 'function'에서 가장 빠른 것으로 보입니다. 그러나 Firefox obj instanceof Function에서는 확실한 승자가 있습니다.
저스틴 워 켄틴

7
부분에 관해서 : typeof는 변수 또는 속성이 정의되어 있지 않은지 확인하는 데만 사용해야합니다. 에서 javascript.info/tutorial/type-detection대해서 typeof의 좋은 사용 의 경우와 정반대임을 섹션 및 다음 한 저자 상태,
콘라드 Madej

11
알렉스, 왜 typeof가 정의되지 않은 것을 확인하는 데에만 사용되어야하는지 궁금합니다. 이름은 그것이 존재하는지 여부뿐만 아니라 무언가의 유형을 확인하는 것이 목적임을 시사합니다. 형식 검사를 위해 사용할 때 발생할 수있는 기술적 인 문제 나 문제가 있습니까? 경고가있는 경우 다른 사람이 넘어지지 않도록 목록을 작성하는 것이 좋습니다.
jinglesthula

14
불합리하게 지나치게
복잡한

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

44
그냥 같은 몇 가지 조심 typeof Object, typeof Date그리고 typeof String,하는 모든 수익 'function'도.
Dave Ward

358
@ 데이브, 나는 그것이 기능이기 때문에 문제가 무엇인지 잘 모르겠습니다.
Matthew Crumley

6
차이점은 무엇입니까 if (v instanceOf Function)?
mquandalle

10
@mquandalle instanceof다른 문서 (iframe 등)에서 온 함수를 검사하는 경우를 제외하고 는 큰 차이 가 없습니다. 성능이 다릅니다.
rvighne

8
허용 된 답변과 달리 이것은 비동기 기능에서도 작동합니다. 를 들어 asyncfunctionToCheck, getType.toString.call(functionToCheck)==='[object AsyncFunction]'어디에typeof asyncfunctionToCheck === 'function'
TDreama

132

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 참조)


이 방법을 사용해야하는 특별한 이유가 typof있습니까?
sv_in

1
Underscore 버전은 대부분의 브라우저에서 훨씬 빠릅니다. 참조 : jsperf.com/alternative-isfunction-implementations
Paul Rosania

13
나는 밑줄을 좋아하지만 간단하지만 강력합니다. 즉,이 구현은 그러한 속성을 가진 객체에 의해 스푸핑 될 수 있다는 점에 주목할 가치가 있습니다.
studgeek

3
@PaulRosania 오늘이 성능 테스트를 우연히 발견 하고 검증 4와 같은 검증 및 추가 테스트 데이터로 업데이트 했습니다. 브라우저 테스트 범위를 늘리려면 실행하십시오. 초당 많은 작업으로 인해 속도가 느리지 만 (많은 테스트로 인해) 구현 차이가 하나 있습니다 (자바 스크립트 콘솔을 열고 페이지를 다시로드하면 오류 메시지가 기록 될 수 있음). 참고 : 개정판 3에는 isFunctionD (만 기반)가 추가되었으며 Underscore의 "빠른"버전보다 훨씬 빠른typeof == "function" 것 같습니다 .
Joel Purra

6
Underscore.js가 대체 구현 테스트에 대한 위에서 언급 한 개정판 4가 아니라 개정판 12 에 있으므로이 답변은 현재 약간 오해의 소지가 있습니다 isFunction(). 현재 dandean이 제안한 것과 매우 유사한 것을 사용합니다.
Jonathan Eunice

112

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

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

10
함수가 다른 프레임 컨텍스트로 전달 된 경우 첫 번째 솔루션이 실패합니다. 예를 들어, iframe에서 top.Function !== Function. 확실하게, 두 번째 것을 사용하십시오 (디버그 중에 "함수"의 철자가 틀리면 수정 될 것입니다).
MaxArt

오타에 대한 요점 : 오타가있는 코드는 오타가있는 다른 버그보다 빨리 실패 할 가능성이 높습니다. typeof === "function"이 가장 깨끗한 솔루션입니다. 또한 사용하는 "최상의"솔루션은 instanceof프레임 간 검사와 같은 여러 전역을 고려하지 않으며 잘못된 부정을 반환 할 수 있습니다.
brainkim

84

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

56

@grandecomplex : 솔루션에 상당한 양의 세부 정보가 있습니다. 다음과 같이 작성하면 훨씬 명확합니다.

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

Object.prototype.toString.call은 관심있는 다른 자바 스크립트 유형에 유용합니다. null 또는 undefined를 검사하여 매우 강력합니다.
Jason Foglia

49

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


1
... 그리고 (() => (typeof obj === 'function') && doSomething())여전히 가장 빠른 옵션입니다.
darcher

35

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

19

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

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

11

다른 간단한 방법 :

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

1
fn이 정의되지 않으면 오류가 발생합니다
Kamil Orzechowski

fn && fn.constructor === Function이건 어때요?
Yaroslav Melnichuk

9

기능적 스타일에 관심이 있거나 메타 프로그래밍 (예 : 유형 검사)에서 활용하기위한보다 표현적인 접근 방식을 찾는 사람들에게는 Ramda 라이브러리를 보고 그러한 작업을 수행하는 것이 흥미로울 수 있습니다 .

다음 코드에는 순수하고 pointfree 함수 만 포함됩니다.

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

물론, 기능을 "안전"하게하려면 값 nullundefined값을 보호해야합니다 .

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

당신이 Lodash를 사용하는 경우 당신은 그것을 할 수 _.isFunction .

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

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

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

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

이 메소드는 truevalue가 함수이면을 리턴 합니다 false.


4

나는 IE8에서 기본 브라우저 기능을 테스트 할 때, 사용하는 것을 발견 toString, instanceoftypeof작동하지 않았다. 다음은 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

단점은 다른 프로토 타입이 동일한 플래그를 정의 할 수 있다는 것입니다. 그러나 쓸모가 없지만 포함 된 모듈을 완전히 제어 할 수있는 가장 쉬운 방법입니다


foo가 정의되지 않으면 Error와 함께 실패합니다. 완전히 잘못된 기본 프로토 타입을 수정한다고 언급하지 않습니다.
Kamil Orzechowski

3

노드 v0.11부터 표준 util 기능을 사용할 수 있습니다.

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

2
util.isFunction은 사용되지 않습니다
kehers

2

js에서 typeOfoperator 를 사용해야합니다 .

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

0

이전의 답변 중 일부에서 보인 해결책은 typeof를 사용하는 것입니다. 다음은 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]();
  }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.