Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 694
franza Avatar asked Feb 03 '26 07:02

franza


1 Answers

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;
};
like image 184
lonesomeday Avatar answered Feb 04 '26 22:02

lonesomeday



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!