Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial

Rebecca Jensen
11,580 PointsReplacing characters in a string using replace() - function not recognized.
I'm working on a JavaScript exercise to look at a string of digits, then if the number is less than 5, replace it with '0', and if the number is 5 or greater, replace it with '1'.
I'm getting an error, "Cannot read property 'length' of undefined", which doesn't make sense to me. Any idea what I'm doing wrong here?
This is my code:
var numberString = '123456789';
function fakeBin(numberString) {
for ( i = 0; i < numberString.length; i++ ) { //for the length of the argument
var digit = numberString.indexOf(i); //define each digit so we can evaluate them
//var fakeString = ''; //place to add results to a string
if ( digit < 5) { //if digit is less than 5
digit.replace(digit,'0'); //replace that digit with '0'
} else { //if digit is 5 or greater
digit.replace(digit,'1'); //replace that digit with '1'
}
}
return numberString; //return the string with 0's and 1's
}
fakeBin();
An interactive version can be found here: https://repl.it/JssH/3
Thanks!
2 Answers

Steven Parker
242,770 PointsI see a few things which may be causing problems:
- the call of fakeBin at the bottom doesn't give it an argument to work with
- indexing is done by placing a value in brackets after the item, the indexOf method does something else
- the replace method generates a new string, it does not modify the one it is applied to
- the code works on the digit, but then never uses it for anything
- at the end, the original argument is returned unchanged

Steven Parker
242,770 PointsOk, now that you have passed (congratulations! ), here's how I might do it:
function fakeBin(numberString) {
var newString = "";
for (var n of numberString) newString += n < 5 ? '0' : '1';
return newString;
}
And if I wanted to be super compact:
var fakeBin = ns => ns.replace(/[1-4]/g, '0').replace(/[5-9]/g, '1');
Were there any smaller than that?

Rebecca Jensen
11,580 Points whoa.
I didn't know that I could put other things in the for() brackets besides a counter. I'll have to read up on that. Is there a term for what you've put in the for() brackets?
After that, if I were to guess it out, I'd say it goes something like:
"concatenate onto newString" newString += "if n is less than 5? make it zero" n < 5 ? '0' "else, make it 1" : '1';
But then how are you looping through each digit of n?

Steven Parker
242,770 PointsThere are 3 kinds of "for" loops. The one you know, the standard "for" with the 3 clauses, the "for...in" loop, and finally the "for...of" loop that I used here. You'll learn about the last 2 in more advanced courses, but the short explanation of "for...of" is that it steps through the values of the term after "of", and each time assigns the current value to the variable declared before "of". The rest is a ternary expression which you guessed the operation of correctly.

Rebecca Jensen
11,580 PointsThat is compact! Here are some other short answers, though I can't make much sense of them yet:
function fakeBin(x) {
return x.replace(/\d/g, d => d < 5 ? 0 : 1);
}
function fakeBin(x){
return x.split('').map(a => a < '5' ? "0" : "1").join("");
}
The shortest I can find:
fakeBin = x => x.split('').map(e => e < 5 ? 0 : 1).join('');

Steven Parker
242,770 PointsThose last 2 are essentially the same with a different declaration style. They convert the string into an array (split), build a modified array (map), then convert it back into a string (join). But I really like the first one, similar idea to mine but I had forgotten that replace can take a function as the second argument.
Rebecca Jensen
11,580 PointsRebecca Jensen
11,580 PointsAha.
Thank you for the very clear feedback!
I'm using variable[i] instead of indexOf(), and pushing things to an array and then converting it back to a string instead of using replace(). It SEEMS to work on repl.it when I try different string of numbers... however, I am working on a CodeWars challenge, and I when I run it, I see that one test passes, and after that: "newString.push is not a function".
??? Am I using push() incorrectly? I feel like I'm following the clear layout here: https://www.w3schools.com/jsref/jsref_push.asp
Also, I think that there must be a much more efficient way to accomplish this. Hrm.
My code now:
Also at: https://repl.it/JssH/8
Steven Parker
242,770 PointsSteven Parker
242,770 PointsCalling fakebin converts the global newString from an array into a string, so if you call the function more than once (as I'm sure the challenge testing does), you'll get "TypeError: newString.push is not a function" on the second call. To start fresh each time, the initialization of newString (and the variable itself, for that matter) should be moved into the function.
About efficiency, these optimizations come to mind:
I'm hesitant to be too explicit until after you've passed the challenge.
Rebecca Jensen
11,580 PointsRebecca Jensen
11,580 PointsI really appreciate how you can call out my mistakes without spelling out the answer for me! I am definitely learning a lot this way.
I got to this code below to pass the challenge, though I know it could be more efficient. I think it's still good practice for me for tracking where loops end and begin, and where things should go.
-moved newString variable inside the function -changed the positioning of where I converted it to a string, took out the commas, and returned it
Rebecca Jensen
11,580 PointsRebecca Jensen
11,580 PointsWhoa. Now I can see other students' answers, and many are just one line long! Whew! I can see how much learning is ahead of me now.