Why can't this be primitive?

I was messing around with JavaScript and noticed that this never be primitive. What I'm talking about? Let me explain.

Take this feature, for example.

 function test(){ return typeof this; } test.call('Abc'); // 'object' test.call(123); // 'object' 

They are both 'object' and not 'string' or 'number' , as I expected.

After some confusion (and messing with instanceof ), I realized what was going on. 'Abc' closed by a String object, and 123 converted to a Number object.

In any case, my question is why this happens, and how do I convert an object back to its primitive?

I know I can use (String)this or (Number)this , but how to do it if I don't know the type?

EDIT : I tried to do this:

 function element(){ var $e = $(this), $d = $e.closest('div'); } element.call('#myID'); 

and he did not work. this is a String object, and jQuery simply created a collection of objects instead of using a selector to search for the DOM.

+7
source share
4 answers

As others noted, he was forced into an object according to the specification.

It is important to note that if you are in strict mode, coercion does not occur.

 "use strict"; function test(){ return typeof this; } test.call('Abc'); // 'string' test.call(123); // 'number' 

So, the real question is: why aren't you using strict ? -)


As you noted in your comment, you should be able to use .valueOf() if you support implementations that do not support strict mode.

If you are only expecting String, or if you are also expecting a number, but you are not against a number string, you can do this ...

 (this + '') // "Abc" (this + '') // "123" 

"but how can I do this if I don’t know the type"

If you want to know its type, use the generic toString available on Object.prototype to get the internal [[Class]] property.

 Object.prototype.toString.call( this ); "[object String]" Object.prototype.toString.call( this ); "[object Number]" 
+5
source

I found it, ECMAScript 5.1

Function.prototype.call

NOTE The value of thisArg is passed unchanged as the value of this . This is a change from version 3, where undefined or null thisArg is replaced by a global object, and ToObject is applied to all other values ​​and this result is passed as the value of this .

This basically says undefined and null , since the first parameter calls this as a global object ( window in the browser context), and all other values ​​are converted to the object using ToObject .


Due to typeof inconsistencies, I recommend using Object.prototype.toString.call , which returns consistent values ​​in each browser tested:

 Object.prototype.toString.call('foo') //[object String] Object.prototype.toString.call(10000) //[object Number] Object.prototype.toString.call(someFunc) //[object Function] ...etc 

you can compare the result in this script

+3
source

spec says this always an object.

Otherwise, if Type (thisArg) is not an object, set the ToObject (thisArg) binding to this object.

+2
source

As far as I understand, this does not make sense outside the object-oriented context, it will always point to some instance of the object. Therefore, by definition, it cannot be primitive.

Furthermore, it seems that your test function returns a typeof test function (which is this in this context), and not the parameters you pass.

0
source

All Articles