7

I'm curious, becouse i thought that

Object.prototype.toString.call(null)

return [object Object], but now i was checking that in Chrome and FF and both returned [object Null]. Now the question is, wether i can assume that Object.prototype.toString will always tell me the good type?

Until now, i was checking every type with this method, but not for null values, i was checking null values by

obj === null;

Thanks!


Note for clarification: this 'problem' is not a serious case, since atm i'm using

function isNull(obj) {
  return obj === null;
}

function isUndefined(obj) {
  return typeof obj === 'undefined';  
}

which works just fine, but if Object.prototype.toString.call() would work sufficient in older browsers, i could drop these two functions and extend my solution with null and undefined like:

var types = ['Object', 'Number', 'String', 'Array', 'Function', 
 'Date', 'RegExp', 'Boolean', 'Error', 'Null', 'Undefined'].reduce(function(prev, type) {
    prev['[object ' + type + ']'] = type.toLowerCase();
 return prev;
  }, {});

function isType(type) {
  return function(obj) {
 return getType(obj) === type;
  };
}

function getType(obj) {
  return types[Object.prototype.toString.call(obj)];
}

var isNull = isType('null');

document.querySelector('#console').textContent = isNull(null);
<div id='console'></div>
Attila Kling
  • 1,717
  • 4
  • 18
  • 32
  • And why would you need to check for every type ? – adeneo Sep 17 '14 at 16:30
  • 4
    here is from FF: `Starting in JavaScript 1.8.5 toString() called on null returns [object Null], and undefined returns [object Undefined] ...` https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString – pms Sep 17 '14 at 16:30
  • 2
    @AmadeusDrZaius it's not that weird if you read the documentation. – Sterling Archer Sep 17 '14 at 16:34
  • And here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString#Using_toString_to_detect_object_type – Dave Newton Sep 17 '14 at 16:34
  • @AmadeusDrZaius: Which browser (version)? `Object.prototype.toString.apply("hello")` gives `"[object String]"` for me in Chrome and FF. – Felix Kling Sep 17 '14 at 16:35
  • @FelixKling Never mind, I was being stupid. I'll delete the comment. – Chris Middleton Sep 17 '14 at 16:36
  • Also: http://es5.github.io/#x15.2.4.2 – Felix Kling Sep 17 '14 at 16:37
  • Thanks for the comments and aswers, then new question, if i would like to support older browsers and environments, can i use toString to check for null and undefined, or its something that legacy browsers can't use? Now i do obj === null for isNull() and typeof obj === 'undefined' for isUndefined(). If {}.toString would work for older browsers, i would drop these two methods. – Attila Kling Sep 17 '14 at 16:46
  • @Jim-Y Why do you want to use `toString` to check for null and undefined instead of just `typeof` or direct comparison? – Chris Middleton Sep 17 '14 at 16:48
  • I'm already using a terse ~way~ for checking values, and if toString would work efficient on null and undefined, then i could drop 2 unnecessary functions :) Not a serious case, but you know, i was curious :) – Attila Kling Sep 17 '14 at 16:49

2 Answers2

4

This is defined in EcmaScript 5.1 Section 15.2.4.2 - Object.prototype.toString():

When the toString method is called, the following steps are taken:

  1. If the this value is undefined, return "[object Undefined]".
  2. If the this value is null, return "[object Null]".
  3. Let O be the result of calling ToObject passing the this value as the argument.
  4. Let class be the value of the [[Class]] internal property of O.
  5. Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".

EcmaScript 5 defined it differently:

When the toString method is called, the following steps are taken:

  1. Let O be the result of calling ToObject passing the this value as the argument.
  2. Let class be the value of the [[Class]] internal property of O.
  3. Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".
Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
4

Oriol's answer is right, but I wanted to add that there is a difference between calling toString directly on, say, a number or a string, vs. using Object.prototype.toString.

The Object.prototype.toString function is general, so if we do

var x = "hello, world";
alert(Object.prototype.toString.call(x));

we will see "[Object string]".

However, if we call toString directly, instead, like this:

alert(x.toString());

we will see "hello, world". The reason for this is that toString in the second example is really String.prototype.toString, which is different from the generic Object.prototype.toString method. The same distinction occurs with a number like 6:

var y = 6;
alert(Object.prototype.toString.call(y)); // "[Object Number]"
alert(y.toString()); // "6"
alert(Number.prototype.toString.call(y)); // also "6"

In this case, the primitive value 6 is being boxed into an instance of Number when you do y.toString(). When you concatenate strings, it's the object's toString method that gets called, not Object.prototype.toString, which is why alert("I am " + y + " years old") produces "I am 6 years old", not "I am [Object Number] years old".

Since null has no Null prototype or anything like that, doing null.toString() will produce an error.

Chris Middleton
  • 5,654
  • 5
  • 31
  • 68