antonjs
antonjs

Reputation: 14318

Javascript: the most efficient way to check if a variable is a function, an array or a object

Let's suppose we have a variable that could be a function, object or array.

I want to find the most efficient way to determinate it.

I think the following way is not optimized because if I know that isFunction = true I don't want to calculate the other variables (isArray, isObject);

What is the order to calculate them, which optimize the resources, by using the ternary operation?

var isFunction,
    isArray,
    isObject;

var obj = function () {};

isFunction = (typeof obj === "function") ? true : false;
isArray = (obj.length > 0) ? true : false;
isObject = (typeof obj === "object") ? true : false;

console.log(isFunction , isArray , isObject ); // true, false, false (the good way)
console.log(isFunction , isArray , isObject ); // true, undefined, undefined

Upvotes: 2

Views: 275

Answers (2)

hugomg
hugomg

Reputation: 69944

The following functions are ways how the dojo toolkit tests for arrays, functions, etc

isString = function(it){
    return (typeof it == "string" || it instanceof String); // Boolean
},

isArray = function(it){
    return it && (it instanceof Array || typeof it == "array"); // Boolean
},

isFunction = function(it){
    return opts.call(it) === "[object Function]";
},

isObject = function(it){
    return it !== undefined &&
        (it === null || typeof it == "object" || lang.isArray(it) || lang.isFunction(it)); // Boolean
},

isArrayLike = function(it){
    return it && it !== undefined && // Boolean
        // keep out built-in constructors (Number, String, ...) which have length
        // properties
        !lang.isString(it) && !lang.isFunction(it) &&
        !(it.tagName && it.tagName.toLowerCase() == 'form') &&
        (lang.isArray(it) || isFinite(it.length));
},

I don't see the point of trying to optimize this kind of code. If you really cared about optimizations, you should probably use simpler non-overloaded functions where these checks are not necessary.

Upvotes: 0

zzzzBov
zzzzBov

Reputation: 179086

I'd say this is as "efficient" as I can make it. It's short, but readable, and should do the job correctly. It will be performant in modern browsers that have a native implementation of some, and the nature of some is such that it only executes the callback until one of the items in the array meets the condition.

Just make sure you add in Array.prototype.some for older browsers.

function isOneOf(obj, types) {
  var type;
  type = Object.prototype.toString.call(obj);
  return types.split(' ').some(function (t) {
    return type.indexOf(t) > -1;
  });
}

isOneOf({}, 'Array Object Function');

This should work for Array, Date, Error, Function, Null, Number, Object, String, and Undefined. I haven't done thorough cross-browser testing with all those types, so make sure to do some good unit-testing before taking my word for it.

Upvotes: 2

Related Questions