0

Before I start I would like to give a future thanks to all the help/input received.

I am having a major problem with an exercise in Object Oriented Programming by Stoyan Stefanov. While it may be a problem with an exercise, I think this question can help a lot of beginning programmers (like me), especially with OOP. The Exercise is in Chapter 4 Question #4.

I will copy and paste the prompt: "Imagine the String() constructor didn't exist. Create a constructor function MyString() that acts like String() as closely as possible. You're not allowed to use any built-in string methods or properties, and remember that String() doesn't exist."

I understand for-in loops should not be used with strings. But I am using it in this case just for the exercise. It is also what the author, Stoyan Stefanov, suggested as part of the prompt.

Here is the code I have so far. I have created a constructor called MyString with a couple of methods and properties.

function MyString(value)
{
  var valUpdated = this.valueOf(); //problems are occuring here; the value in valUpdated should be a string, not an object 

  this.charAt = function(pos) 
  {
      try
      {
        if(typeof pos !== "number")
        {
          throw new Error("Please input a valid number");
        }
        else
        {
          for (var char in valUpdated)
          {
            return char; //problem is occurring here, when I use the original value parameter and not "valUpdated", the first char returned is 0, as expected, otherwise, its "charAt," referring to a method of the object stored in "valUpdated"
            if(Number(char) === pos) //if using the original parameter value (and not valUpdated), this part of the code works just fine
            {
                return char;
            }
          }
        }
      }
      catch (e)
      {
         return "This error occured " + e;
      }
  };  

  this.findLength = function () 
  {
    var counter = 0;
    for (var char in value)
    {
      counter++;
    } 
    return counter;
  };

  this.length = this.findLength();

  this.valueOf = function()  
  {
    var type = typeof value,
        valueNew = value; //i chose not to update the existing variable value to avoid some concept of oop in javascript that i most likely missed
    if (type === "number" || type === "object" || type === "null"      
        || type === "undefined")
    {
      valueNew = "'" + value + "'"; 
      return valueNew;
    }
    else
    {
      return valueNew;
    }
  };
}

The problem is all occurring on the first line of the constructor where I am trying to use a method, .charAt() of this constructor, MyString() to update the value I will then use in all further methods (this way I can first check to make sure that the value inputted (i.e. the referenced string in the variable value) used is a valid string or has been first converted into a valid string... and this is where all my problems are occurring).

Creating the refined value variable is done at the bottom of the code with the .valueOf() method. I am trying to use this method and return its value to "var valUpdated" at the top of the code block. The problem occurs, for instance, when I use the valUpdated variable in the .charAt() method. For some reason, when I use the valUpdated variable, it references an object even though it should reference a string i.e. the returned value of .valueOf() is a string but for some reason the typeof valUpdated variable is an object.

This can be verified in the "for...in" loop. where that first "return char" statement in the .charAt() method (this return char statement is used only for error tracking) returns "charAt" instead of a digit referring to the string character. This must mean that the value in valUpdated is an object since a "for...in" loop iterates over each property of an object. However, if var valUpdated was a string, which it should be according to the return value of the method .valueOf(), the "property" would be the index of the string and the object would be the actual string.

The most interesting part is if I use the regular parameter "value," the parameter used with the MyString constructor, the char variable works as it should and the value of the char is a digit referring to the character in the referenced string.

***Update: when I take this entire block of code:

  var valUpdated = this.valueOf(); 

  this.charAt = function(pos) 
  {
      try
      {
        if(typeof pos !== "number")
        {
          throw new Error("Please input a valid number");
        }
        else
        {
          for (var char in valUpdated)
          {
            return char;
            if(Number(char) === pos) 
            {
                return char;
            }
          }
        }
      }
      catch (e)
      {
         return "This error occured " + e;
      }
  };  

...and move it down to the bottom of the constructor, the char variable is now returning a number. Can someone please explain this? I thought Javascript could take functions defined below in the code and use it above where it is defined?

  • thats a lot to read... – user2502227 Sep 07 '13 at 21:44
  • haha yes it is. took me forever to right. But I think it can really help alot of people out. – user2484802 Sep 07 '13 at 21:55
  • Using var in the constructor to simulate private instance specific variables and then having to put all the functions in the constructor body because they can't use the "privates" otherwise always makes me a little sad when I see that. http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Sep 08 '13 at 12:05

2 Answers2

2

Want to be of help here after reviewing this item page.149 Exercise 4 from Stefanov, S. (2013) "Object-Oriented JavaScript, Second Edition". Birmingham, UK: Packt.

The problem: Without using "String()" or built-in methods, write a JavaScript constructor that will be able to take new arguments and return a string.

I believe the author was expecting something like this solution: (implicit coercion to string)

function MyString(str) {
   this.str = str;
    return '' + this.str + '';
}

var s = new MyString('hello');

it passes all the tests in the Exercises

> s.length;
"5"
> s.[0];
"h"
> s.toString();
"hello"
> s.valueOf();
"hello"
> s.charAt;
"e"
1

The valueOf function you called is not the function you defined, but the function of Object, see link here Object.valueOf. In the definition of a constructor, this key word refers to the object being created when you new an instance, so this.valueOf = function(){...}; will create a property on this instance, here is a function, but since it's a function expression, you won't see it at the first line, var valUpdated = this.valueOf(); is calling the method of Object which happens to be a superclass of all the user defined obejcts.

You may also want to read something about how javascript prototype chain works, becasue you are talking about OOP.

grape_mao
  • 1,153
  • 1
  • 8
  • 16
  • I agree with what you are saying. The only thing, from what it seems after I moved everything below where I defined the new method .valueOf(), is that the super class Object method can be replaced by your own method of the same name as long as you use it after you define it. – user2484802 Sep 08 '13 at 03:30
  • @user2484802 it's ture, but may not be a good thing to do. Actually in javascript there is only prototype, it's like super class in java, but still different. When a function or property be called, the search starts from the object being called, if non found, it then goes on to the prototype. Normally functions are defined on prototype(can be seen as a property of an object, you could read some articles for more details), they will be shared by all the instance so that you don't create same methods for each instance. – grape_mao Sep 08 '13 at 04:22