tags:

views:

54

answers:

2

Hi All,

I'm wondering why it seems that adding a method to the prototype of a string literal seems to work, but adding a property does not? I was playing with ideas in relation to this question, and have the following code:

String.prototype._str_index1 = 0;
String.prototype._str_reset = function() {
    this._str_index1 = 0;
};
String.prototype._str_substr = function(len) {
  var ret = this.substr(this._str_index1, len);
  this._str_index1 = this._str_index1 + len;
  return ret;
};

var testString = new String('Loremipsumdolorsitamet,consectetur');
log(testString._str_substr(5));
log(testString._str_substr(4));
​

This works fine. If however I change the third-last line to:

var testString = 'Loremipsumdolorsitamet,consectetur';

...it seems that although the method _str_substr exists and is callable on the string literal, the value of the property _str_index1 is always 0.

What's up?

+2  A: 

This happens because the object is created and immediately thrown away when the assignment is made, because it's a string literal.

So with the first version, an object is created and kept, so testString is an object, not a string literal. In the second case, an object is created and thrown away, so all properties get lost...

Now try replacing that line with this:

var testString = 'Loremipsumdolorsitamet,consectetur'._str_substr();

Interesting, right? It still returns a string primitive, but that could be fixed...

String.prototype._str_substr = function(len) {
  var ret = this.substr(this._str_index1, len);
  this._str_index1 = this._str_index1 + len;
  return new String(ret);
};

Of course these are just suggestions designed to help explain why literals act differently than objects, not real-world recommendations...

no
I don't get it.
spender
No me neither. @no, I have no idea what you mean.
sje397
“the object is created and immediately thrown away when the assignment is made” sounds like an object is created and thrown away on the *initial* assignment (`var testString = …`), not when invoking `_str_substr`.
Marcel Korpel
Marcel - it _is_.
no
Hmm, I'm looking for it in the ECMAScript specification, but can't find it (at least not at this hour). But if that would be the case, the method of the `String` object can't be called after the string assignment is made. The string primitive has to be converted every time a method of the `String` object is invoked.
Marcel Korpel
Marcel: I think we're talking about the same thing... AFAIK a String object is temporarily created when a string is encountered and then thrown away. Maybe I'm wrong about that, the point was that it isn't an object from the time its declared, it's a primitive; stateless except for its value. When you call 'methods' of a string primitive it's just like applying String.prototype.x to the literal string.
no
You're correct (about that we're talking about the same thing).
Marcel Korpel
+6  A: 

The string primitive is converted to a transient String object every time you try to invoke a method of the String object (the JavaScript engine internally converts a string primitive to a String object when necessary). After this function returns, the String object is (unobtrusively) converted back to a string primitive (under the hood) and this new primitive is returned (and most of the time assigned to a variable); every time a method of the String object is invoked.

So, after each invocation of testString._str_substr, _str_index1 is thrown away with the object and a new object (with a reset _str_index1) is created when _str_substr is called again.

See also MDC:

Because JavaScript automatically converts between string primitives and String objects, you can call any of the methods of the String object on a string primitive. JavaScript automatically converts the string primitive to a temporary String object, calls the method, then discards the temporary String object.

Marcel Korpel
Yeah, that's pretty much what I was trying to say :)
no