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.