/    Sign up×
Community /Pin to ProfileBookmark

Mimicking built-in functions

I’m at the end of chapter 4 of “Object Oriented Javascript” where the author, Stoyan Stefanov, asks you to recreate the String() method of the global Object with a constructor function named MyString(). He then asks you to test your recreation with the following code:

var s = new MyString(‘hello’);
s.length;
s.concat(‘ world!);
s.charAt(‘2’);
etc. etc.

He suggests using a for-in to loop through the input string. I’m stumped on this. Any suggestions? Just hints though, I don’t want anyone to writ out the whole function.

Thanks,

commakozzi

to post a comment
JavaScript

10 Comments(s)

Copy linkTweet thisAlerts:
@commakozziauthorJun 28.2009 — I got a start at it with:

<i>
</i>function MyString(string) {
[indent]var a = [];
var i = 0;
for (i in string) {
[indent]a[i] = i;
return a;[/indent]
}
[/indent]


however this only returns a comma delimited list of integers representing each index of the input string array, not the actual letter.
Copy linkTweet thisAlerts:
@rnd_meJun 28.2009 — the trouble is that a for-in will not reveal the built in properties you are looking for, like concat, charAt, etc...

the simplest way to do it is to just inherit from String:
[CODE]
function MyString(s){
var o= new String(s);
return o;
}

var s = new MyString('hello');
s.length;
s.concat(' world!');
s.charAt('2');
[/CODE]


that's not enough code to consist of a spoiler, so just examine what it's doing.

everytime you use the "new" keyword, it creates a prototype object for the returned value.

you can set that prorotype to (almost) whatever you want, but by default, it's the same as the constructor's .prototype.

for the purposes of learning,

they might want you to define your own functions to recreate the functionality of concat and charAt, currently inherited from String.

or, perhaps they just want you to use inheritances like the above example, i don't know.

btw, the posted code is not really a constructor, just a wrapper.
Copy linkTweet thisAlerts:
@commakozziauthorJun 28.2009 — the trouble is that a for-in will not reveal the built in properties you are looking for, like concat, charAt, etc...

the simplest way to do it is to just inherit from String:
[CODE]
function MyString(s){
var o= new String(s);
return o;
}

var s = new MyString('hello');
s.length;
s.concat(' world!');
s.charAt('2');
[/CODE]

[/QUOTE]


Yeah, problem is he doesn't want you to use String(). Sorry, I should have posted his instructions exactly:


"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." -- Stoyan Stefanov, "Object Oriented JavaScript"
[/quote]


I would have posted that the first time, but I was posting from my phone... sorry. The book hasn't covered prototyping or inheritance yet.
Copy linkTweet thisAlerts:
@commakozziauthorJun 28.2009 — Yeah, problem is he doesn't want you to use String(). Sorry, I should have posted his instructions exactly:

[/QUOTE]


I should add, too, that the exercise in question came from Chapter 4: Objects.

Therefore: (?)
<i>
</i>function MyString(string) {
[INDENT]charAt: function() {
[INDENT]var a = [];
var i = 0;
for (i in string) {
[INDENT]a[i] = i;
return a[i];[/INDENT]
}[/INDENT]
}[/INDENT]

etc. etc.


Maybe this is the right direction?
Copy linkTweet thisAlerts:
@rnd_meJun 28.2009 — ok. well, it's going to be impossible to re-create it exactly. how yould you set the initial string value, without using a string? furthermore, to provide a string finished product, must one invoke String's .toString() at some point. this doesn't have to be explicit however, so i think we can live within the limitations and allowances of "as closely as possible", and make something that works.


Since we can't use a string to hold our data, let's use an array, and pretend that the initial setting string and the output string don't really use String:



[CODE]
function MyString(s){
this.val=s.split(""); //immediately make array to pretend we don't have to use a string
with(this){
this.length={valueOf:[COLOR="DarkGreen"]function(){return val.length;}[/COLOR]};
}

this.concat=function(str){this.val=this.val.concat(str.split(""));return this;}
this.charAt=function(n){return this.val[n];}
this.bold=function(){ this.val=["<b>"].concat(this.val).concat("</b>");return this;}

[COLOR="DarkGreen"] this.toString=function(){return this.val.join("");}
this.valueOf=function(){return this.val.join("");}[/COLOR]
}

[/CODE]


the dark green magic functions are how you make an object behave like a primitive...

BTW: i can't believe this is before prototypes, "new" is almost pointless without prototypes...
Copy linkTweet thisAlerts:
@commakozziauthorJun 29.2009 — That's what I was looking for, rnd me. I'm trying not to read the whole response, because you gave it away. However, I can't help myself. Yeah, the author did that in chapter three also. He has you do an exercise that requires knowledge that you won't get until the next chapter. Thanks for your help!
Copy linkTweet thisAlerts:
@rnd_meJun 29.2009 — sorry if i let the cat out of the bag, but it's something i couldn't get to work without the main .valueOf functionality, and there's a certain way that methods must be built that i wanted to demonstrate.

this is actually a little different than the built-in strings in that it always passes by reference; a pointer.

this means that when you apply .bold() to a MyString, it clobbers the actual string instead of merely returning a new marked-up copy.

don't worry, you still have about 20 more string methods to build...
Copy linkTweet thisAlerts:
@commakozziauthorJul 09.2009 — rnd me, if you're still monitoring this thread:

I think I figured out what the author is trying to get you to do. He says to use a for in to loop through the string input:

<i>
</i>function MyString(str) {
[indent]var a = [];
for (var i in str) {
[indent]a[i] = str[i];[/indent]
}
return a;
this.length = a.length;[/indent]
}


That's not the complete solution yet, but it seems more "correct" than the direction we were going in. Although your solution was working, you were still using the split() method of the built-in String() object.
Copy linkTweet thisAlerts:
@rnd_meJul 09.2009 — rnd me, if you're still monitoring this thread:

I think I figured out what the author is trying to get you to do. He says to use a for in to loop through the string input:

<i>
</i>function MyString(str) {
[indent]var a = [];
for (var i in str) {
[indent]a[i] = str[i];[/indent]
}
return a;
this.length = a.length;[/indent]
}


That's not the complete solution yet, but it seems more "correct" than the direction we were going in. Although your solution was working, you were still using the split() method of the built-in String() object.[/QUOTE]


i wasn't sure what they wanted...

let me suggest 2 improvements to the new code:
[CODE]
for (var i in str) {
if(str.hasOwnProperty(i){
a[a.length] = str[i];
}
}
[/CODE]


hasOwnProperty will filter out any string prototypes, and a[a.length] will omit extra spaces where those other properties would go.

glad to hear youre learning and pushing forward, it's worth it.
Copy linkTweet thisAlerts:
@commakozziauthorJul 17.2009 — Not sure if this is just a fundamental misunderstanding by me, but why would un-commenting line 7 (return a) cause this constructor function to not return "true" on line 18 (m.hasOwnProperty("concat"))? In other words, I'm trying to have m[1] return "e" while m.concat(" world") returns "hello world", but when I un-comment line 7 (return a) m.hasOwnProperty("concat") returns "false". I believe that's because the this.concat = function, etc. is ignored and the concat() from the prototype is shining through. Is that correct or no? If it is, what's really going on and how do I fix it?

<i>
</i>function MyString(str) {
var a = [];
for (var i in str) {
a[i] = str[i];
//console.log(a[i]);
}
return a;
this.length = a.length;
this.concat = function(b) {
//return a.join("") + b;
}
}
var m = new MyString("hello");
//m;
//m.length;
//m.toString();
//m.concat(" world");
//m.concat.toString();
//m.hasOwnProperty("concat");
//m[1];
×

Success!

Help @commakozzi spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 6.2,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @meenaratha,
tipped: article
amount: 1000 SATS,

tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,
)...