Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I am reading "Object-Oriented JavaScript" by Stoyan Stefanov to learn JavaScript and in the end of the chapter named "Objects", there's an exercise that asks you to implement your own String object. I have implemented some methods of String (not all), I'd be happy if you could check and let me know how it could be done better:

function MyString(primitive) {
    this.length = 0;
    var i = 0;
    // Here length is calculated and the indexer is set.
    for (var c in primitive) {
        this[i++] = primitive[c];
        this.length++;
    }

    this.toString = function() { return primitive; };
    this.valueOf = this.toString;
    this.substring = function(start, end) {
        var result = '';

        // Edge cases for the parameters.
        if ((typeof end !== 'number' && typeof parseInt(end) !== 'number') || end > this.length)
            end = this.length;
        if (end <= 0 || isNaN(end)) {
            end = start;
            start = 0;
        }

        for (var i = start; i < end; i++) {
            result += this[i];
        }

        return result;
    }
    this.charAt = function(i) {
        var x = parseInt(i);
        x = isNaN(x) ? 0 : x;
        return this.substring(x, x+1);
    };

    return this;
}

var s = new MyString('hello');
console.log(s.length);
console.log(s[0]);
console.log(s.toString());
console.log(s.valueOf());
console.log(s.charAt(1));
console.log(s.charAt('2'));
console.log(s.charAt('e'));
console.log(s.substring(1, 3));

Any and all suggestions are welcome. I'm completely new to JavaScript and would love to hear my mistakes.

share|improve this question
    
You'll want to use prototypes. –  Ṣhmiddty Jul 2 '13 at 22:03
    
The length property should be read-only. –  Ṣhmiddty Jul 2 '13 at 22:08
    
I know it should be read-only but I have no idea at the moment how to make it so. And the prototypes chapter is the next one (I'm reading it now). Could you add an answer with your suggested improvements? –  hattenn Jul 2 '13 at 22:10

1 Answer 1

up vote 2 down vote accepted

Some information up front:

  1. Object.defineProperty is an Ecmascript 5 feature, and is not available in older browsers (IE < 9).

  2. There is likely a cleaner way of doing all of this.

This is a basic skeleton:

function MyString(primitive) {
    var length = 0, a;   // private internal variable to track length, and our iterator

    // the loop below basically ensures that this string object is immutable. 
    for(a in primitive){
        (function(char){
            Object.defineProperty(this, length++, {
                get:function(){return char;}
            });
        }).call(this,primitive[a]);
    }

    // we can "get" the length, but we can't "set" it.
    Object.defineProperty(this, "length", {
        get:function(){return length;}
    });

    return this;
}

// defining methods on the prototype of an object allows us to share the same instance 
// of the method without recreating it for each instance of the object. 
// (reduced memory footprint)
MyString.prototype.toString = function(){
    return [].join.call(this, '');  
    // since our object is "array-like", we can use array methods on it. 
}

MyString.prototype.charAt = function(index){
    return this[index];
}
share|improve this answer
    
Note: Be aware of the problem when using this[index], not supported in IE < 8, see string.charAt(x) or string[x]? –  Xotic750 Jul 4 '13 at 13:22
    
@Xotic750 This is true but in this case it should work since he is not accessing the string but the MyString object which has an internal 0: 'a' etc representations –  ScareCrow Jan 6 at 8:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.