0

I am having problems wrapping my brain around a scoping issue using a prototype function in an array while sorting it. I can make it work on a static item, but when I attempt to generalize to work on the array I start seeing "is not a function" errors. Here is my current rendition of the code. Any help would be appreciated.

function Automobile(year, make, model, type) {
    this.year = year; //integer (ex. 2001, 1995)
    this.make = make; //string (ex. Honda, Ford)
    this.model = model; //string (ex. Accord, Focus)
    this.type = type; //string (ex. Pickup, SUV)

}
Automobile.prototype.logMe = function(bool) {

    console.log("Working"); //testing function
    if (bool == true) {
        console.log(this);
    }

};

/*Sample Array*/
var automobiles = [
    new Automobile(1995, "Honda", "Accord", "Sedan"),
    new Automobile(1990, "Ford", "F-150", "Pickup"),
    new Automobile(2000, "GMC", "Tahoe", "SUV"),
    new Automobile(2010, "Toyota", "Tacoma", "Pickup"),
    new Automobile(2005, "Lotus", "Elise", "Roadster"),
    new Automobile(2008, "Subaru", "Outback", "Wagon")
];

/*This function sorts arrays using an arbitrary comparator.*/
function sortArr(comparator, array) {


    array.sort(function(a, b) {
        return comparator(a, b);
    });
    return array;
}

function exComparator(int1, int2) {
    if (int1 > int2) {
        return true;
    } else {
        return false;
    }
}


function yearComparator(auto1, auto2) {
    return exComparator(auto1.year, auto2.year);
}

/* Output*/
console.log("*****");
console.log("The cars sorted by year are:");
forEach(sortArr(yearComparator, automobiles), automobiles.logMe(true)); //This is not right!


function forEach(array, doStuff) {
    for (var i = 0; i < array.length; i++)
        doStuff(array[i]);
}
4
  • 2
    Sort comparator functions are not supposed to return just true or false. Instead, they're supposed to return a negative number, zero, or a positive number, to indicate that the first value should go before the other, if they're the same, or that the second value should go before the first. Commented Apr 24, 2016 at 21:55
  • 2
    also, your sortArr function is functionally identical to array.sort(comparator) Commented Apr 24, 2016 at 21:57
  • Your comparison function is invalid, but that's not the issue you're having with forEach. Commented Apr 24, 2016 at 22:03
  • What i don't understand is.. while you are inventing forEach from scratch why did you use Array.prototype.sort to invent your own sort? Joke aside you should definitely study Array methods. Commented Apr 24, 2016 at 22:19

2 Answers 2

1

Your reported problem has nothing whatsoever to do with the sorting (although your sort comparator function is also invalid - see below).

The error you're getting is because you're passing the result of automobiles.logMe to your forEach function instead of a reference to that function. In any event, that logMe function is a shared instance method, and can't be via the array.

Your sort function is also unnecessary - your entire sort/display loop could be written:

automobiles.sort(yearComparator).forEach(function(auto) {
     auto.logMe(true);
});

and then strip out the unneeded sortArr and forEach functions that just duplicate standard ES5 functionality.

To fix the comparator it needs to return one of (-ve, 0, +ve), not false / true. For numeric comparisons it suffices to just return the difference between the two numbers:

function yearComparator(auto1, auto2) {
    return auto1.year - auto2.year;
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

Sign up to request clarification or add additional context in comments.

4 Comments

I see exactly what you mean and that all works like a charm. Unfortunately I am attempting to meet some assignment requirements that require the use of a sortArr function and gave me the true/false comparator. It seems like I am being made to jump through extra hoops to meet requirements that really don't leave me with great code... but since I started javascript last week, I can't say that I know what I am talking about
In which case your sortArr function potentially needs to call comparator twice, and return the correct -ve, 0, +ve result based on whether a>b, b>a, or neither (i.e. they're equal). That doesn't address the actual problem posed though, which solely relates to how you tried to pass automobiles.logMe(true) to the forEach function.
Sweet, I have it all worked out now. Thanks a ton for your help. I packaged your input into my sortArr function, rewrote their supplied comparator and removed a giant pile of unneeded code that was only serving to confuse me further. It works now and is far prettier.
Glad to have helped. FWIW, if they actually gave you that comparator function then IMHO that's pretty bad teaching. Any code that reads if (condition) return true else return false can be trivially reduced to return condition !
0

The main problem is "automobiles.logMe(true)". automobiles is the array of Automobile objects. Each element in array automobiles can get access to their prototype's function logMe(), but not the array itself.

Also, the doStuff(array[i]) reflects that you should learn more about three important functions (call, apply, bind). Having a bit look at this article will help: http://javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals/

3 Comments

Thanks for the tip! Dang right I need to learn more about those functions. Thanks for the link.
I disagree on the use of .call or .apply here (and .bind is certainly not relevant). The standard ES5 Array.prototype.forEach does not support setting this separately on each iteration - it relies on the supplied callback to do so, if required. It can set a common context for every iteration, though.
I ended up not using that bit of code, but they are definitely functions that I need to learn more about so the link is very useful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.