Common type inference(類型判斷) and some useful tutorials Back

Type Inference(類型判斷)

Array

Firstly, we will talk about the type inference of arrays. And in my post, "Javascript中判断数组的正确姿势", I have done an analysis for different kinds of ways in inferring about their advantages/disadvantages.

Here I have given the right code:

function isArray(a) {
    Array.isArray ? Array.isArray(a) : Object.prototype.toString.call(a) === '[object Array]';
}

While underscore has given the following code:

/** 
 * Is a given value an array?
 * Delegates to ECMA5's native Array.isArray
 */
_.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) === '[object Array]';
};

nativeIsArray has been pointed to the method Array.isArray in ES5, while toString has been pointed to the method Object.prototype.toString.

Object

In underscore, both function and object variables are treated as an object, only without null.

/**
 * Is a given variable an object?
 * An object can be also a function */
 */
_.isObject = function(obj) {
    var type = typeof obj;
    return type === 'function' || type === 'object' && !!obj;
};

Arguments, Function, String, Number, Date, RegExp, Error

All of those type can be inferred by calling Object.prototype.toString.call:

// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
// 其他类型判断
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
    _['is' + name] = function(obj) {
        return toString.call(obj) === '[object ' + name + ']';
    };
});

However, isArguments will return [object Object] under IE 9, so we can infer by checking existence of the attribute callee. You know, arguments.callee can return the method of current arguments.

/**
 * Define a fallback version of the method in browsers (ahem, IE < 9), where
 * there isn't any inspectable "Arguments" type.
 */
if (!_.isArguments(arguments)) {
    _.isArguments = function(obj) {
        /** If it's under IE 9, then to judge whetehr it has the property called `callee` */
        return _.has(obj, 'callee');
    };
}

Utility Class Inference(工具類判斷)

DOM Elements

You can just infer an element whether it's a DOM element by ensuring that it's not a null and nodeType is 1:

// Is a given value a DOM element?
_.isElement = function(obj) {
    /** make sure object is not `null` and the property `nodeType` of this object is `1` */
    return !!(obj && obj.nodeType === 1);
};

NaN

NaN has belonged to Number type, and Object.prototype.toString.call(NaN) should be [object Number]. Besides, NaN is not equal to itself, so we can infer it like this: (Some bugs, see #13)

/**
 * Is the given value `NaN`? (NaN is the only number which does not equal itself).
 * NaN is a Number object which is not equal to itself
 */
_.isNaN = function(obj) {
    return _.isNumber(obj) && obj !== +obj;
};

Notice that: isNaN has been changed to the native method isNaN, which will also return true for many other not-number values, such as undefined. That means:

console.log(isNaN(undefined));      /** => true     */
console.log(_.isNaN(undefined));    /** => false    */

Therefore, the new _.isNaN has been modified like this:

_.isNaN = function(obj) {
    return _.isNumber(obj) && isNaN(obj);  
};

Why adding a + before the object? The answer is clear after running the fllowing code:

var a = new Number(NaN);

console.log(a !== a);               /** => false    */
console.log(a !== +a);              /** => true     */
Empty Comments
Sign in GitHub

As the plugin is integrated with a code management system like GitLab or GitHub, you may have to auth with your account before leaving comments around this article.

Notice: This plugin has used Cookie to store your token with an expiration.