답변:
확실히 밑줄의 방법이 더 효율적이지만 효율성이 문제가되지 않을 때 확인하는 가장 좋은 방법은 @Paul Rosania가 링크 한 밑줄의 페이지에 기록되어 있습니다.
밑줄에서 영감을 얻은 최종 isFunction 함수는 다음과 같습니다.
function isFunction(functionToCheck) {
return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}
isFunctionA
다른 방법과 비교하여 구현 차이를 보여줍니다.
typeof(obj) === 'function'
에서 가장 빠른 것으로 보입니다. 그러나 Firefox obj instanceof Function
에서는 확실한 승자가 있습니다.
if (typeof v === "function") {
// do something
}
typeof Object
, typeof Date
그리고 typeof String
,하는 모든 수익 'function'
도.
if (v instanceOf Function)
?
instanceof
다른 문서 (iframe 등)에서 온 함수를 검사하는 경우를 제외하고 는 큰 차이 가 없습니다. 성능이 다릅니다.
asyncfunctionToCheck
, getType.toString.call(functionToCheck)==='[object AsyncFunction]'
어디에typeof asyncfunctionToCheck === 'function'
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
있습니까?
typeof == "function"
것 같습니다 .
isFunction()
. 현재 dandean이 제안한 것과 매우 유사한 것을 사용합니다.
몇 가지 방법이 있으므로 모두 요약하겠습니다.
function foo (v) {if (v instanceof Function) {/ * 무언가를 수행 * /}};가장 성능이 뛰어나고 (문자열 비교가 아님) 우아한 솔루션-instanceof 연산자는 브라우저에서 매우 오랫동안 지원되었으므로 걱정하지 마십시오. IE 6에서 작동합니다.
function foo (v) {if (typeof v === "function") {/ * 무언가를 수행 * /}};단점은
typeof
자동 실패, 나쁨에 취약하다는 것입니다. 따라서 오타가있는 경우 (예 : "finition")-이 경우`if`는 false를 반환하고 나중에 오류가 있음을 알 수 없습니다. 당신의 코드
함수 isFunction (functionToCheck) { var getType = {}; return functionToCheck && getType.toString.call (functionToCheck) === '[객체 함수]'; }이것은 솔루션 # 1 또는 # 2에 비해 이점이 없지만 읽기가 훨씬 어렵습니다. 이것의 개선 된 버전은
함수 isFunction (x) { return Object.prototype.toString.call (x) == '[object Function]'; }그러나 여전히 솔루션 # 1보다 의미가 훨씬 적습니다.
top.Function !== Function
. 확실하게, 두 번째 것을 사용하십시오 (디버그 중에 "함수"의 철자가 틀리면 수정 될 것입니다).
instanceof
프레임 간 검사와 같은 여러 전역을 고려하지 않으며 잘못된 부정을 반환 할 수 있습니다.
@grandecomplex : 솔루션에 상당한 양의 세부 정보가 있습니다. 다음과 같이 작성하면 훨씬 명확합니다.
function isFunction(x) {
return Object.prototype.toString.call(x) == '[object 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
더 많은 브라우저를 지원하고 비동기 기능을 포함하는 것은 다음과 같습니다.
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
다른 간단한 방법 :
var fn = function () {}
if (fn.constructor === Function) {
// true
} else {
// false
}
fn && fn.constructor === Function
이건 어때요?
기능적 스타일에 관심이 있거나 메타 프로그래밍 (예 : 유형 검사)에서 활용하기위한보다 표현적인 접근 방식을 찾는 사람들에게는 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);
물론, 기능을 "안전"하게하려면 값 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 ));
그러나이 솔루션은 고차 함수의 광범위한 사용으로 인해 다른 사용 가능한 옵션보다 성능이 떨어질 수 있습니다.
당신이 Lodash를 사용하는 경우 당신은 그것을 할 수 _.isFunction .
_.isFunction(function(){});
// => true
_.isFunction(/abc/);
// => false
_.isFunction(true);
// => false
_.isFunction(null);
// => false
이 메소드는 true
value가 함수이면을 리턴 합니다 false
.
나는 IE8에서 기본 브라우저 기능을 테스트 할 때, 사용하는 것을 발견 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 이하에서 이것이 항상 작동하지는 않는 곳을 읽었습니다.
아래는 나에게도 효과가있는 것 같습니다 (에서 테스트 됨 node.js
).
var isFunction = function(o) {
return Function.prototype.isPrototypeOf(o);
};
console.log(isFunction(function(){})); // true
console.log(isFunction({})); // false
함수 프로토 타입에서 플래그를 정의하고 테스트하려는 인스턴스가 상속되었는지 확인할 수 있다고 생각합니다.
플래그를 정의하십시오.
Function.prototype.isFunction = true;
그런 다음 존재하는지 확인하십시오.
var foo = function(){};
foo.isFunction; // will return true
단점은 다른 프로토 타입이 동일한 플래그를 정의 할 수 있다는 것입니다. 그러나 쓸모가 없지만 포함 된 모듈을 완전히 제어 할 수있는 가장 쉬운 방법입니다