I'm manipulating the prototype of Object
so that I can add some extension methods.
I've found out that typeof
operator always returns object
in case the operand is this
:
Object.prototype.logType = function () { console.log(typeof this); }
"Hello".logType()
output of code above is object
instead of string
. I know that in JavaScript everything is indeed an object
, However I need to know the exact type of the value of this
. How can I achieve that?
When you call a method on a primitive, JS automatically wraps that primitive in its associative object wrapper, so:
"Hello".logType()
becomes:
new String("Hello").logType()
hence, this
inside of your logType function refers to the wrapped primitive value, giving you an object. You can call .valueOf()
to grab the primitive value wrapped in the object:
Object.prototype.logType = function () { console.log(typeof this.valueOf()); }
"Hello".logType(); // string
(1).logType(); // number
true.logType(); // boolean
1n.logType(); // bigint
Symbol().logType(); // symbol
(() => {}).logType(); // function
({}).logType(); // object
Or, you can use strict mode as suggested in the comments, as that keeps this
as the original primitve:
Object.prototype.logType = function () { "use strict"; console.log(typeof this); }
"Hello".logType(); // string
(1).logType(); // number
true.logType(); // boolean
1n.logType(); // bigint
Symbol().logType(); // symbol
(() => {}).logType(); // function
({}).logType(); // object
When passed as this
outside of strict mode, you have the very rare case that you encounter a primitive in their wrapped object form ("boxed"), as instance of String
:
You can therefore check if your method was called on a string using this instanceof String
instead of typeof this === 'string'
. If you want to differentiate between strings and objects that inherit from String
, you could use this.constructor === String
instead.
To get a "regular" string back (or number for Number
, or boolean from Boolean
, etc.), you can call this.valueOf()
(This means you could also write typeof this.valueOf()
- but note that this may be misleading because any object could return, say, a string from its valueOf
method without actually having been a string originally.)
Note: You cannot differentiate between 'abc'.yourMethod()
and new String('abc').yourMethod()
this way because you get an instance of String
either way.
(Also interesting: Seems like for newer types like BigInt
or Symbol
you cannot manually create such a wrapper instance, new BigInt(1n)
will fail. But (function () { return this }).call(1n)
would achieve the same, although I have no idea why anybody would want that...)
All that said: The easiest way to get the exact behavior you want (this
being the actual string) is by defining your function in a context that is in strict mode:
(function {
'use strict'
Object.prototype.logType = function () { console.log(typeof this); }
})()
Now it will work as intended.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With