franza
franza

Reputation: 2317

Messing with this in prototype's method

Ok, here's the situation:

var vowels = ['a', 'i', 'y', 'e', 'o', 'u'];
String.prototype.isVowel = function () {
  return vowels.indexOf(this) !== -1;
};

alert('a'.isVowel());

It will alert 'false' since this references not 'a' but its prototype. To make it work we need to make a little change.

String.prototype.isVowel = function () {
  return vowels.indexOf(this[0]) !== -1;
};

alert('a'.isVowel());

This will work since String.prototype contains all characters of original string. It's a hack actually and I don't like it.

But what do we need to do to make this code work?

Number.prototype.is5 = function () { return this === 5; }

alert((5).is5()); //will alert 'false'

Or we just don't need to touch prototypes?

Upvotes: 3

Views: 130

Answers (2)

lonesomeday
lonesomeday

Reputation: 237905

The problem is what is called boxing. If you have a primitive value and then call a method on that value, it will be wrapped as an object of the type String, Number, Boolean, or what have you. This is equivalent to calling new String('a'), for instance. (It is documented in the ECMAScript specification.)

new String('a') is not the same as 'a'. It therefore is not found in the array.

What you need to do, therefore, is convert the value back into the primitive value. You can always accomplish this with the valueOf method:

return vowels.indexOf(this.valueOf()) !== -1;

Your method is to call this[0]. This works, because it gets the first character from the string as a primitive, which is then found in the string. The downside is that ab would also be considered a vowel by this method.


Similarly with numbers:

 Number.prototype.is5 = function () { return this.valueOf() === 5; };

One other point: this is the default behaviour of Javascript. It is not obvious or intuitive, as you have shown. In ECMAScript 5, "strict mode" was created, where all kinds of undesirable behaviours are disabled. Auto-boxing is one of them. So, if you use a modern browser, this will have the expected behaviour:

Number.prototype.is5 = function () {
    "use strict";
    return this === 5;
};

Upvotes: 11

Scott Mermelstein
Scott Mermelstein

Reputation: 15397

Look at the way you declared String.prototype.isVowel, which worked acceptably. Now look at Number.prototipe.is5(). See the differences?

  • prototipe is misspelled, and should be prototype.

  • is5() shouldn't have () after it.

That leaves you with this:

Number.prototype.is5 = //...

You should've gotten an error when setting Number.prototipe.is5(), so maybe these are all just typos in posting.

Upvotes: 0

Related Questions