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

Discussion in 'Javascript' started by Csaba Gabor, May 9, 2006.

  1. Csaba  Gabor

    Csaba Gabor Guest

    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
    Csaba Gabor, May 9, 2006
    #1
    1. Advertising

  2. Csaba Gabor wrote:
    > 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.
    Richard Cornford, May 9, 2006
    #2
    1. Advertising

  3. "Csaba Gabor" <> writes:

    > 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
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, May 9, 2006
    #3
  4. Csaba  Gabor

    Csaba Gabor Guest

    Richard Cornford wrote:
    > Csaba Gabor wrote:
    > > 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.
    Csaba Gabor, May 9, 2006
    #4
  5. Csaba  Gabor

    VK Guest

    Csaba Gabor wrote:
    > 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).
    VK, May 9, 2006
    #5
  6. JRS: In article <>
    , dated Tue, 9 May 2006 08:35:34 remote, seen in
    news:comp.lang.javascript, Csaba Gabor <> posted :
    >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("") }

    --
    © John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
    <URL:http://www.jibbering.com/faq/> JL/RC: FAQ of news:comp.lang.javascript
    <URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
    <URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
    Dr John Stockton, May 9, 2006
    #6
  7. "VK" <> writes:

    > 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
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
    Lasse Reichstein Nielsen, May 9, 2006
    #7
  8. Csaba  Gabor

    Csaba Gabor Guest

    Dr John Stockton wrote:
    > JRS: In article <>
    > , dated Tue, 9 May 2006 08:35:34 remote, seen in
    > news:comp.lang.javascript, Csaba Gabor <> posted :
    > >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.
    Csaba Gabor, May 10, 2006
    #8
  9. Csaba Gabor wrote :
    <snip>
    > ... (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.
    Richard Cornford, May 10, 2006
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. June Lee
    Replies:
    2
    Views:
    790
    Jim Cobban
    Apr 13, 2008
  2. Replies:
    9
    Views:
    175
    Thomas 'PointedEars' Lahn
    May 26, 2006
  3. gp
    Replies:
    0
    Views:
    100
  4. Replies:
    3
    Views:
    259
  5. javascript fish
    Replies:
    0
    Views:
    163
    javascript fish
    Oct 11, 2008
Loading...

Share This Page