This is a fascinating question... Thanks for your post!
To be honest, I am a bit surprised by Object(this)
because JavaScript seems to coerce anything to object (using wrappers) in situations where this
could potentially be a primitive value.
If we try to change this
with Function.prototype.bind()
, JavaScript always returns an object (a function is an object):
var foo = function () {
console.log(this, typeof this);
}.bind('foo');
var bar = function () {
console.log(this, typeof this);
}.bind(1337);
var baz = function () {
console.log(this, typeof this);
}.bind(false);
var qux = function () {
console.log(this, typeof this);
}.bind(NaN);
var quux = function () {
console.log(this, typeof this);
}.bind(undefined);
var corge = function () {
console.log(this, typeof this);
}.bind(null);
var grault = function () {
console.log(this, typeof this);
}.bind([]);
var garply = function () {
console.log(this, typeof this);
}.bind({});
var waldo = function () {
console.log(this, typeof this);
}.bind(/regex/);
var fred = function () {
console.log(this, typeof this);
}.bind(function () {});
foo(); // String { 0: "f", 1: "o", 2: "o" } object
bar(); // Number { 1337 } object
baz(); // Boolean { false } object
qux(); // Number { NaN } object
quux(); // Window object
corge(); // Window object
grault(); // Array [ ] object
garply(); // Object { } object
waldo(); // /regex/ object
fred(); // function fred<() function
If we try to change this
with Function.prototype.call()
or Function.prototype.apply()
, once again, JavaScript always returns an object:
Array.prototype.foo = function () {
console.log(this, typeof this);
};
['foo'].foo(); // Array [ "foo" ] object
Array.prototype.foo.call('bar'); // String { 0: "b", 1: "a", 2: "r"} object
Array.prototype.foo.call(42); // Number { 42 } object
Array.prototype.foo.call(true); // Boolean { true } object
Array.prototype.foo.call(NaN); // Number { NaN } object
Array.prototype.foo.call(undefined); // Window object
Array.prototype.foo.call(null); // Window object
Array.prototype.foo.call({}); // Object { } object
Array.prototype.foo.call(/regex/); // /regex/ object
Array.prototype.foo.call(function () {}); // function () function
In JavaScript, we know that native objects may be useful for type conversion when they are not used as constructors but as regular functions. Number
, String
and Boolean
are quite convenient:
var num = 1337,
str = '',
bool = true;
console.log(Number(str), typeof Number(str));
console.log(Number(bool), typeof Number(bool));
console.log(String(num), typeof String(num));
console.log(String(bool), typeof String(bool));
console.log(Boolean(num), typeof Boolean(num))
console.log(Boolean(str), typeof Boolean(str));
For the record, here is what we get with explicit conversions through Object()
:
console.log(typeof Object(false), Object(false) instanceof Boolean);
console.log(typeof Object('bar'), Object('bar') instanceof String);
console.log(typeof Object(42), Object(42) instanceof Number);
console.log(typeof Object(NaN), Object(NaN) instanceof Number);
console.log(typeof Object(undefined), Object(undefined) instanceof Object);
console.log(typeof Object(null), Object(null) instanceof Object);
console.log(typeof Object(['foo']), Object(['foo']) instanceof Array);
console.log(typeof Object({}), Object({}) instanceof Object);
console.log(typeof Object(/regex/), Object(/regex/) instanceof RegExp);
console.log(typeof Object(function () {}), Object(function () {}) instanceof Function);
Now it is obvious that Object(this)
can be used to convert any primitive value for this
and get a wrapper object instead. If this
is already an object, it has no effect:
var obj1 = {baz: 'Baz'},
obj2 = Object(obj1);
var arr1 = ['foo', 'bar'],
arr2 = Object(arr1);
var reg1 = /regex/,
reg2 = Object(reg1);
var fun1 = function () { return 'Hello!'; },
fun2 = Object(fun1);
console.log(arr1 === arr2);
console.log(obj1 === obj2);
console.log(reg1 === reg2);
console.log(fun1 === fun2);
Moreover, Object
is weird because it acts in the same way, whether it is called with new
or not:
var foo = Object('foo'),
bar = new Object('bar');
console.log(foo);
console.log(bar);
I may be wrong, but my conclusion is the following: given that this
is always coerced to an object, Object(this)
is not necessary. However, it indicates explicitly what happens implicitly to avoid ambiguity and improve code comprehension.
What do you think?
EDIT
torazaburo is right: strict mode is the key! When functions are in strict mode, primitive values for this
are not coerced! This is probably the most reasonable explanation for explicit conversion with Object(this)
...
Function.prototype.bind()
var foo = function () {
'use strict';
console.log(this, typeof this);
}.bind('foo');
var bar = function () {
'use strict';
console.log(this, typeof this);
}.bind(1337);
var baz = function () {
'use strict';
console.log(this, typeof this);
}.bind(false);
var qux = function () {
'use strict';
console.log(this, typeof this);
}.bind(NaN);
var quux = function () {
'use strict';
console.log(this, typeof this);
}.bind(undefined);
var corge = function () {
'use strict';
console.log(this, typeof this);
}.bind(null);
var grault = function () {
'use strict';
console.log(this, typeof this);
}.bind([]);
var garply = function () {
'use strict';
console.log(this, typeof this);
}.bind({});
var waldo = function () {
'use strict';
console.log(this, typeof this);
}.bind(/regex/);
var fred = function () {
'use strict';
console.log(this, typeof this);
}.bind(function () {});
foo(); // foo string
bar(); // 1337 number
baz(); // false boolean
qux(); // NaN number
quux(); // undefined undefined
corge(); // null object
grault(); // Array [ ] object
garply(); // Object { } object
waldo(); // /regex/ object
fred(); // function fred<() function
Function.prototype.call()
Array.prototype.foo = function () {
'use strict';
console.log(this, typeof this);
};
['foo'].foo(); // Array [ "foo" ] object
Array.prototype.foo.call('bar'); // bar string
Array.prototype.foo.call(42); // 42 number
Array.prototype.foo.call(true); // true boolean
Array.prototype.foo.call(NaN); // NaN number
Array.prototype.foo.call(undefined); // undefined undefined
Array.prototype.foo.call(null); // null object
Array.prototype.foo.call({}); // Object { } object
Array.prototype.foo.call(/regex/); // /regex/ object
Array.prototype.foo.call(function () {}); // function () function