returned type of -this- from String.prototype.repeat()

C

Csaba Gabor

I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

Just something I thought I'd share,
Csaba Gabor from Vienna
 
R

Richard Cornford

Csaba said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

Maybe alos:-

return this.toString();

or

return String(this);
Just something I thought I'd share,

OK. But why were you surprised? the - this - keyword _always_ refers to
an object.

Richard.
 
L

Lasse Reichstein Nielsen

Csaba Gabor said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this; ....
Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

It's not so surpricing. The "this" operator always refer to an object,
and that is what you return.

When you write
(stringExpression).methodCall()
(e.g. "foo".repeat(1)), the string value (a primitive type) is promoted
to an object as if by (new String("foo")) and the method is called on
that object. That's why you are allowed method calls on primitive values
at all.

What you can do is:
if (n < 2) { return this.toString(); }
which is equivalent to what you are doing except that it saves the
empty concatenation (but costs a method call).

Likewise, for a slight bit of efficiency (as if it mattered), the
loop could be:
for (var aStr = [this.toString()];--n>0;) aStr.push(this.toString());
(or better:
var s = this.toString();
for (var aStr = ;--n>0;) aStr.push(s);
for large n's it saves n calls to toString)

I wouldn't worry about performance in the trivial cases, as they won't
take long anyway, and just do the more readable:

String.prototype.repeat = function repeate(n) {
var rep = [];
var s = this.toString(); // care a little about performance for the big n's
while(n > 0) {
rep.push(s);
n--;
}
return rep.join("");
}

/L
 
C

Csaba Gabor

Richard said:
Csaba said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

Maybe alos:-

return this.toString();

or

return String(this);
Just something I thought I'd share,

OK. But why were you surprised? the - this - keyword _always_ refers to
an object.

Right after posting, I went running from the Opera to the Schloss
Schonbrunn and back, and with the delightful weather, there are patches
of swarming midge's and my eye chanced to run into one, capturing it
under my lower eyelid, which I could only extricate upon return. As if
I didn't have enough bugs to deal with.

Thanks for the speedy reply. The answer to your question is: In four+
years of javascript coding, this is the first time (I remember seeing)
that the distinction between string vs. object actually makes a
difference. I mean, I have read this distinction between strings and
objects (but never with examples), and when something walks like a
duck, and quacks like a duck for long enough, one tends to forget that
it still might not be a duck under the covers. Javascript has taken
care of the details so well, that in my mind a string has become a
special object, sort of like a function is.
 
V

VK

Csaba said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

Just something I thought I'd share,

return (aStr.join("")).toString();
would do the trick too (to cast a String object back to primitive),
unless you have overloaded toString method for other needs.

In JScript you also could do
return (aStr.join("")).valueOf();
but I'm not sure if it's supported in the standard JavaScript (out of
my test pages right now).
 
D

Dr John Stockton

JRS: In article <[email protected]>
, dated Tue, 9 May 2006 08:35:34 remote, seen in
news:comp.lang.javascript said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

ISTM that you can also fix it by removing that line.

Try

String.prototype.repeat = function(n) {
// repeats the string n times
for (var aStr = [] ; n-- > 0;) aStr[aStr.length] = this ; // or push
return aStr.join("") }
 
L

Lasse Reichstein Nielsen

VK said:
return (aStr.join("")).toString();
would do the trick too (to cast a String object back to primitive),

Not necessary. The join method always returns a primitive string
value. The join operation will convert each element in the array to a
primitive string during the operation, if they aren't already.

You will just wrap the string value in a new String object for calling
the toString method.

The problem the original poster experienced was only in the n<2 case
where the value of "this" was returned.
unless you have overloaded toString method for other needs.

In JScript you also could do
return (aStr.join("")).valueOf();

Same thing. The valueOf method on String.prototype is equivalent to
the toString method. Both return the primitive string value contained
in the object.
but I'm not sure if it's supported in the standard JavaScript (out of
my test pages right now).

It's ECMAScript compliant.

/L
 
C

Csaba Gabor

Dr said:
JRS: In article <[email protected]>
, dated Tue, 9 May 2006 08:35:34 remote, seen in
news:comp.lang.javascript said:
I wrote a .repeat(n) function for strings which seemed to work fine:

String.prototype.repeat = function(n) {
// repeats the string n times
if (n<1) return "";
if (n<2) return this;
for (var aStr = [this];--n>0;) aStr.push(aStr[0]);
return aStr.join("");
}

Only I was a little surprised to get "object" (instead of "string")
when I tried:
alert (typeof ("x".repeat(1)));

I fixed this by modifying ...
if (n<2) return this+"";

ISTM that you can also fix it by removing that line.

Try

String.prototype.repeat = function(n) {
// repeats the string n times
for (var aStr = [] ; n-- > 0;) aStr[aStr.length] = this ; // or push
return aStr.join("") }

which is exactly what Lasse proposed at the end of his initial response
(only his solution is more efficient because he sets var
s=this.toString() (and by the way, is there any difference in
efficiency between that and var s=String(this); ?)

What you've shown is how my function started out. I'm using it in key
event handlers which can potentially involve replacement of many KBs of
text in textareas (to compensate for some FF bugs). And then I
thought, "Hold the phone... in the vast majority of cases, I'm going to
be calling this with n=1 so why should I be making extra copies of this
string?" And that's what led to the special cases.
 
R

Richard Cornford

Csaba Gabor wrote :
... (and by the way, is there any difference in
efficiency between that and var s=String(this); ?)
<snip>

It is probably less efficient as the - String - constructor called as a
function with an object argument implicitly calls the object's -
toString - method, implying the additional overhead of the - String -
function call. Implementation's may optimise this out, but also may not.

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top