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

JavaScript Build a REST API With Express Communicating with Mongo through Mongoose Extending Mongoose

Takuya Hirata
Takuya Hirata
23,296 Points

sortAnswers function

I am not sure why the sortAnswers function can be called without arguments (a and b). Can anybody clarify, please?

3 Answers

Brendan Whiting
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Brendan Whiting
Front End Web Development Techdegree Graduate 84,735 Points

I think this line of code is what you’re referring to:

this.answers.sort(sortAnwers)

In this case, we’re not calling sortAnswers right here, we’re passing in the function as an argument. Inside the .sort() method, it will call sortAnswers under the hood. This is a tricky concept to understand in JavaScript. Functions are objects that can be passed around as arguments.

When we define a function, we use parens and the parameter names: var sortAnswers = function(a, b) { … }. When we call the function, we use parens and the arguments: sortAnswers(x, y). But when we pass that name of the function in as an argument we don’t call it with the parens as in the example above.

The thing that gets confusing is often we pass in an anonymous function in as an argument where we do use the parens and parameter names because we’re defining it in the same place as we’re passing it as an argument, for example: this.answers.sort(function(a, b) {…}). That often misleads people about what’s going on with functions in JavaScript.

There are a couple other workshops on Treehouse about functions that can give you some more practice dealing with these concepts:

Callback Functions in JavaScript

JavaScript Array Iteration Methods

Takuya Hirata
Takuya Hirata
23,296 Points

Thank you Brendan! I think I understand passing the function name to the sort(). My question is when the sort() method calls the sortAnswers function, how does the method know that the sortAnswers needs 2 arguments and when the function gets 2 arguments? Hope this makes sense.

Thanks again!!

Brendan Whiting
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Brendan Whiting
Front End Web Development Techdegree Graduate 84,735 Points

Good question. The short answer is that it doesn’t know…

I’m not exactly sure how the .sort() function is implemented under the hood in JavaScript. But I can guess and try to cobble something to illustrate the point. Let’s say I add a new method to the Array prototype called sortTheItems.

Array.prototype.sortTheItems = function(sortingFunction) {
    function swap(array, i, j) {
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    for(var i = 0; i < this.length; i++) {
        for(var j = 1; j < this.length; j++) {
            const previous = this[j - 1];
            const next = this[j];
            if (sortingFunction(previous, next) > 0) {
                swap(this, j - 1, j)
            }
        }
    }
    return this;
}

(This is not the best way to sort, I’m just doing a clumsy version of bubble sort stolen from here, In real life it’s probably some very efficient merge sort.)

So here I’m saying it takes a parameter called sortingFunction. Then later on, it calling sortingFunction(previous, next). This sortTheItems method on the prototype doesn’t know that the function you pass in will take two arguments. But it’s trusting that you’ve passed one in that you’ve defined as taking two arguments. (Or you could not pass in an argument and it would use a default sort function that it has stored internally). This is something that is one of the downsides of loose typing in JavaScript.

I could pass in a proper function that will work and take two arguments:

const arr = [1, 4, 2, 5, 3];

function sortNumbersAscending(x, y) {
    if (x < y) {
        return -1;
    } else if (x > y) {
        return 1;
    } 
    return 0;
}
arr.sortTheItems(sortNumbersAscending) // [ 1, 2, 3, 4, 5 ]

Or I could pass in something that does not take in two arguments:

function badSortingFunction(singleArg) {
    return "oops..."
}
arr.sortTheItems(badSortingFunction) // [ 1, 4, 2, 5, 3 ]

It doesn’t explode, it just doesn’t work. In other languages, like Java or TypeScript, arguments can be defined as required to meet a certain interface. And if it doesn’t meet that interface it wouldn’t compile. So then the .sort() method would know that the function you pass in takes those arguments because the compiler signed off on it. But in JavaScript, it’s just kind of trusting it doesn’t know.

Takuya Hirata
Takuya Hirata
23,296 Points

Thank you so much Brendan! That makes it clear. I appreciate it!