Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does passing a string as "this" cause this weirdness?

Tags:

javascript

I'm trying to understand why javascript is doing something unexpected (to me). Here's a bit of code that's purely for example. In other words, I don't actually want to extend String (I'm actually binding to functions and stuff). So this is plain javascript with no libraries.

var s = 'blah';

String.prototype.foo = function () {
  console.log('this === s:', this === s);
  console.log('this == s:', this == s);
  console.log('typeof this:', typeof this);
  console.log('typeof s:', typeof s);
  console.log('this:', this);
  console.log('s:', s);
};

s.foo()

And here's the output in Safari's script console:

this === s: false
this == s: true
typeof this: object
typeof s: string
this: [object Object]
s: blah

Similar output in IE, FF, Chrome, etc.

I'm trying to wrap my head around why this === s is not true. Also why this is an "object" but s is a "string".

What's going on here?

like image 790
jep Avatar asked Oct 22 '11 02:10

jep


1 Answers

"Also why this is an "object" but s is a "string"."

It'll be easier if we start with this one.

This is because when you call a method on a primitive value, it is converted to its object wrapper for you (since that's where the methods are). This means that the this value in the function will be the object wrapper, and not the primitive string.

It's as though you were doing this:

new String( s ).foo();

So this explains the typeof result and the [object Object] output.


"I'm trying to wrap my head around why this === s is not true."

This is probably more understandable now. Because this is not a reference to the original string, but rather its object wrapper, you're not comparing identical items by any definition of ===.

The reason == works is that it does type coercion. The Object wrapper is converted to a string primitive, and so you end up with an equal comparison.


You should note that if you're running your code in strict mode, and you call the method on a primitive, the value of this will be the primitive instead of its object wrapper.

like image 53
user113716 Avatar answered Sep 21 '22 23:09

user113716