Если забить на термины и попытаться просто объяснить что происходит - первый вызов sum записывает переданное значение в переменную currentSum и создает функцию, которая сможет всегда достать эту переменную (это называется замыкание). Т. е. где бы и когда бы Вы не вызвали функцию f она всегда будет ссылаться на переменную currentSum (причем это не разные копии переменной, это именно одна и та же переменная). Затем созданная функция возвращается как результат sum. При вызове того, что вернулось из sum (т.е. вызове f) общение снова произойдет с currentSum. Т.е. примерно так:
sum(1)(2)(3) =>
sum(1) возвращает f и currentSum = 1
f(2) возвращает f и currentSum += 2 == 3
f(3) возвращает f и currentSum += 3 == 6
Ну и когда Вы захотите увидеть результат, то вступает в силу f.toString = function() { return currentSum; };, которая переопределяет метод, который вызывается при попытке отобразить функцию как строку. Так как f всегда возвращает f, то после последнего этапа currentSum будет равен 6 и вернется f. Делая alert(sum(1)(2)(3)) Вы по большому счету пытаетесь отобразить вернувшуюся функцию. Происходит обращение к toString, которая отображает именно currentSum, а не что-то другое. Это на пальцах. Но лучше почитать то, что Вам посоветовали.