99 lines
3.0 KiB
JavaScript
99 lines
3.0 KiB
JavaScript
/**
|
|
* @file Determine whether a given value is a function object.
|
|
* @version 3.3.0
|
|
* @author Xotic750 <Xotic750@gmail.com>
|
|
* @copyright Xotic750
|
|
* @license {@link <https://opensource.org/licenses/MIT> MIT}
|
|
* @module is-function-x
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
var attempt = require('attempt-x');
|
|
var fToString = Function.prototype.toString;
|
|
var toBoolean = require('to-boolean-x');
|
|
var isFalsey = require('is-falsey-x');
|
|
var toStringTag = require('to-string-tag-x');
|
|
var hasToStringTag = require('has-to-string-tag-x');
|
|
var isPrimitive = require('is-primitive');
|
|
var normalise = require('normalize-space-x').normalizeSpace;
|
|
var deComment = require('replace-comments-x');
|
|
var funcTag = '[object Function]';
|
|
var genTag = '[object GeneratorFunction]';
|
|
var asyncTag = '[object AsyncFunction]';
|
|
var ctrRx = /^class /;
|
|
var test = ctrRx.test;
|
|
|
|
var hasNativeClass = attempt(function () {
|
|
// eslint-disable-next-line no-new-func
|
|
return Function('"use strict"; return class My {};')();
|
|
}).threw === false;
|
|
|
|
var testClassstring = function _testClassstring(value) {
|
|
return test.call(ctrRx, normalise(deComment(fToString.call(value), ' ')));
|
|
};
|
|
|
|
var isES6ClassFn = function isES6ClassFunc(value) {
|
|
var result = attempt(testClassstring, value);
|
|
|
|
return result.threw === false && result.value;
|
|
};
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Function` object.
|
|
*
|
|
* @private
|
|
* @param {*} value - The value to check.
|
|
* @param {boolean} allowClass - Whether to filter ES6 classes.
|
|
* @returns {boolean} Returns `true` if `value` is correctly classified,
|
|
* else `false`.
|
|
*/
|
|
var tryFuncToString = function funcToString(value, allowClass) {
|
|
if (hasNativeClass && allowClass === false && isES6ClassFn(value)) {
|
|
return false;
|
|
}
|
|
|
|
return attempt.call(value, fToString).threw === false;
|
|
};
|
|
|
|
/**
|
|
* Checks if `value` is classified as a `Function` object.
|
|
*
|
|
* @param {*} value - The value to check.
|
|
* @param {boolean} [allowClass=false] - Whether to filter ES6 classes.
|
|
* @returns {boolean} Returns `true` if `value` is correctly classified,
|
|
* else `false`.
|
|
* @example
|
|
* var isFunction = require('is-function-x');
|
|
*
|
|
* isFunction(); // false
|
|
* isFunction(Number.MIN_VALUE); // false
|
|
* isFunction('abc'); // false
|
|
* isFunction(true); // false
|
|
* isFunction({ name: 'abc' }); // false
|
|
* isFunction(function () {}); // true
|
|
* isFunction(new Function ()); // true
|
|
* isFunction(function* test1() {}); // true
|
|
* isFunction(function test2(a, b) {}); // true
|
|
* isFunction(async function test3() {}); // true
|
|
* isFunction(class Test {}); // false
|
|
* isFunction(class Test {}, true); // true
|
|
* isFunction((x, y) => {return this;}); // true
|
|
*/
|
|
module.exports = function isFunction(value) {
|
|
if (isPrimitive(value)) {
|
|
return false;
|
|
}
|
|
|
|
if (hasToStringTag) {
|
|
return tryFuncToString(value, toBoolean(arguments[1]));
|
|
}
|
|
|
|
if (hasNativeClass && isFalsey(arguments[1]) && isES6ClassFn(value)) {
|
|
return false;
|
|
}
|
|
|
|
var strTag = toStringTag(value);
|
|
return strTag === funcTag || strTag === genTag || strTag === asyncTag;
|
|
};
|