null is a primitive but typeof(null) return “object”
Reason?
In short: it is bug in ECMAScript, and the type should be null. This is a official mistake in the language, carefully kept from 90’s for compatibility.
Examples:
1 2 3 4 5 6 7 8 9 10 11 |
typeof null // object typeof undefined // undefined typeof Boolean // Boolean typeof Number // number typeof String // string typeof Object // object typeof NaN // number typeof true // boolean typeof [] // object typeof new Date // object typeof new String(“test”) // object |
How we can fix this issue?
What we can implement is a better typeof:
Do a typeof to prevent the app from executing input that is not a valid function at all.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var betterTypeOf = function(obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() } betterTypeOf(null); // null betterTypeOf(NaN); // number betterTypeOf({a: 4}); //"object" betterTypeOf([1, 2, 3]); //"array" (function() {console.log(toType(arguments))})(); //arguments betterTypeOf(new ReferenceError); //"error" betterTypeOf(new Date); //"date" betterTypeOf(/a-z/); //"regexp" betterTypeOf(Math); //"math" betterTypeOf(JSON); //"json" betterTypeOf(new Number(4)); //"number" betterTypeOf(new String("abc")); //"string" betterTypeOf(new Boolean(true)); //"boolean" |
isArray
The native can help us to validate Arrays: Array.isArray() method returns true if an object is an array, false if it is not.
1 2 3 4 5 6 7 |
Array.isArray([]); //true Array.isArray([1]); //true Array.isArray(new Array()); //true Array.isArray();// false Array.isArray({});// false Array.isArray(null); // false |
Angular 1.*
Angular implement few fix for this issue:
1 2 3 4 5 |
angular.isString(null); // false angular.isObject(null) // false angular.isElement(null) // false angular.isFunction(null); // false angular.isUndefined(undefined); // true |
AJS 1.2.9 Vs. 1.3.2 isObject()
AJS 1.3.2+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** * @ngdoc function * @name angular.isObject * @module ng * @kind function * * @description * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not * considered to be objects. Note that JavaScript arrays are objects. * * @param {*} value Reference to check. * @returns {boolean} True if `value` is an `Object` but not `null`. */ function isObject(value) { // http://jsperf.com/isobject4 return value !== null && typeof value === 'object'; } |
AJS 1.2.9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * @ngdoc function * @name angular.isObject * @module ng * @kind function * * @description * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not * considered to be objects. Note that JavaScript arrays are objects. * * @param {*} value Reference to check. * @returns {boolean} True if `value` is an `Object` but not `null`. */ function isObject(value){return value != null && typeof value === 'object';} |
Benchmark results
The 1.3.2 is ~1.25 faster than the previous one (this is mainly based on the == and === behaviour)