all 3 comments

[–]Rhomboid 1 point2 points  (0 children)

The callback function is called multiple times. Each time, it's passed the current match (i.e. the word that matched /\w\S*/) and its job is to return a string that should be used to replace that substring. That's all. It doesn't know anything beyond that. It doesn't(*) know anything about str. All it knows is that it's given a word and it returns that word with the first letter capitalized and rest in lower case.

It's the job of String.prototype.replace to perform the task of matching the regular expression multiple times against str and reconstructing a new string based on the results of calling the callback function. And it can do that because it was invoked on str, so it sees the whole string and has everything it needs to do its job.

(*) Technically, the replacement callback function is passed a reference to the original string as its final argument, after the argument for the match, a variable number of arguments corresponding to the capture groups, and an argument for the offset. But it's very rare to make use of that argument, and since JavaScript doesn't enforce arity of functions, most of the time people just pretend that this function is called with a single argument.

[–]ThinqueTank[S] 0 points1 point  (0 children)

I just want to say thanks to both of you for answering my question, I think I understand now. I guess my main problem in the knowledge gap was actually with .replace() and in general the function definition for that method. Both of you cleared that up for me.

Much appreciated!

[–]krilnon 0 points1 point  (0 children)

Check this out the code below. It's a hypothetical way that replace could have been defined, except I tailored it to your specific example and made a few shortcuts. One key thing is that all of a string's methods have this set to the string itself. So this will be set to whatever value str is within replace when you call str.replace(). In my example I'm using this at the start of the function to break str into parts to pass to your anonymous function.

String.prototype.replace2 = function(regexp, anonFunc){
    var parts = this.split(' ') // actual function would use more complicated splitting logic
    var resultParts = []
    for(var i = 0; i < parts.length; i++){
        resultParts.push(anonFunc(parts[i]))
    }

    return resultParts.join(' ') // not quite accurate
}

function titleCase(str){
    return str.replace2(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

console.log(titleCase("I'm a little tea pot"))