Shouldn't that be "return Math.max.apply( Math, this );" and not return Math.max.apply( null, this );
–
HankHNov 3 '09 at 18:24

3

@HankH: maybe. Math.max is akin to a "static" method, so there is no useful this instance inside of it (I hope). So assuming that is true, calling it would run it in the global scope (i.e. window), which is equivalent to passing null as the first paramter to apply/call.
–
Roatin MarthNov 3 '09 at 18:26

4

@HankH: passing null or Math or {} or whatever to apply() or call() has no bearing on the outcome. Math.max does not nor should not reference this internally.
–
Roatin MarthNov 3 '09 at 18:43

Just sharing a jQuery mistake I was making with the code above which took me a long time to debug. A jquery array works fine on everything but the iPad. I had to convert the array to a true native array for it to work. Only affected the single device for some reason Math.max.apply(null, $.makeArray(array));
–
ForrestJul 25 '12 at 21:17

If your arrays contains strings instead of numbers, you also need to coerce them into numbers. The below code does that, but it slows the code down ~10 times on my machine. See http://jsperf.com/min-and-max-in-array/3.

Extending the prototypes of built-in objects like this is a bad idea. If browsers start providing Array.prototype.min themselves in future with a behaviour that subtly differs from yours, future programmers working on your code - or any libraries your code co-exists with that try to use the native implementation - are going to be deeply confused by why they don't get the specified and documented behaviour when they call those methods.
–
Mark AmeryFeb 14 at 14:23

@MarkAmery I'm with you, as it's written now it also breaks for (i in arr) since the properties are enumerable. I guess that the answer is more about providing the function instead of how to call it. Do you suggest that I should update the answer to contain functions taking an array parameter?
–
Linus UnnebäckFeb 16 at 10:37

@LinusUnnebäck I think that would be a good idea - I can imagine a lot of people who view this question copying and pasting the code from here without thinking about it.
–
Mark AmeryFeb 16 at 10:48

Others have already given some solutions in which they augment Array.prototype. All I want in this answer is to clarify whether it should be Math.min.apply( Math, array ) or Math.min.apply( null, array ). So what context should be used, Math or null?

When passing null as a context to apply, then the context will default to the global object (the window object in the case of browsers). Passing the Math object as the context would be the correct solution, but it won't hurt passing null either. Here's an example when null might cause trouble, when decorating the Math.max function:

The above will throw an exception because this.foo will be evaluated as window.foo, which is undefined. If we replace null with Math, things will work as expected and the string "foo" will be printed to the screen (I tested this using Mozilla Rhino).

You can pretty much assume that nobody has decorated Math.max so, passing null will work without problems.

Point taken. However why would someone decorate Foo.staticMethod and reference this? Would that not be a mistake in the design of the decorator? (unless of course they were wanting to reference the global scope, and want to remain independent of the JavaScript engine being used, eg Rhino).
–
Roatin MarthNov 3 '09 at 18:57

The spec is explicit about which specced functions should refer to "the this value" (indeed, that phrase appears 125 times in the specification). Math.max, implemented per spec, does not use this. If somebody overrides Math.max such that it does use this, then they have made its behaviour violate spec and you should throw sharp objects at them. You should not code around that possibility any more than you would code around the possibility that somebody has swapped Math.max and Math.min for the lulz.
–
Mark AmeryFeb 14 at 17:59

Can someone explain how this works? This is pretty dope. Is my understanding correct: arrayMax is a function and we bind something to a property of its prototype? What is this apply.bind and does every prototype have it?
–
SamSep 26 '13 at 17:39

The Math.max() method doesn't allow you to pass in an array. If you have a list of values of which you need to get the largest, you would normally call this function using Function.prototype.apply(), e.g.

I had the same problem, I needed to obtain the minimum and maximum values of an array and, to my surprise, there were no built-in functions for arrays. After reading a lot, I decided to test the "top 3" solutions myself:

discrete solution: a FOR loop to check every element of the array against the current max and/or min value;

The array A was filled with 100,000 random integer numbers, each function was executed 10,000 times on Mozilla Firefox 28.0 on an intel Pentium 4 2.99GHz desktop with Windows Vista. The times are in seconds, retrieved by performance.now() function. The results were these, with 3 fractional digits and standard deviation:

Discrete solution: mean=0.161s, sd=0.078

APPLY solution: mean=3.571s, sd=0.487

REDUCE solution: mean=0.350s, sd=0.044

The REDUCE solution was 117% slower than the discrete solution. The APPLY solution was the worse, 2,118% slower than the discrete solution. Besides, as Peter observed, it doesn't work for large arrays (about more than 1,000,000 elements).

So, it is 35% slower than the simple discrete solution, but it retrieves both the maximum and the minimum values at once (any other solution would take at least twice that to retrieve them). Once the OP needed both values, the discrete solution would be the best choice (even as two separate functions, one for calculating maximum and another for calculating minimum, they would outperform the second best, the REDUCE solution).

Oh now, now @Ionut G. Stan will critique you for the same "wrong context" argument as he did me, since your default comparer (Math.xxx) will be running in the global scope...
–
Roatin MarthNov 3 '09 at 19:00

But, the fastest solution is not always the most optimal solution...
–
Jordan Dillon ChapianJul 12 '14 at 17:52

@JordanDillonChapian I'd agree, but it would be trivial to extend this to a range function that would be the best way to get both the min and max at the same time IMO - as I've done with an update to my answer.
–
tvanfossonJul 13 '14 at 14:25

If you use the library sugar.js, you can write arr.min() and arr.max() as you suggest. You can also get min and max values from non-numeric arrays.

min( map , all = false ) Returns the element in the array with the
lowest value. map may be a function mapping the value to be checked or
a string acting as a shortcut. If all is true, will return all min
values in an array.

max( map , all = false ) Returns the element in the array with the
greatest value. map may be a function mapping the value to be checked
or a string acting as a shortcut. If all is true, will return all max
values in an array.

why do you actually need an object for that? It's just a function that you're using in the end. And also, why are you defining your array twice?
–
gion_13Sep 17 '13 at 5:57

The main solution here is not the array creation convention or assign value to a variable. You can use create array in any you want and assign value as you wish.
–
Yene MulatuSep 25 '13 at 19:49

I know it is not the main solution. In fact it isn't even part of the solution. If it were, maybe i'd down-voted you, but I didn't. I was just curious about why did you write the code that way.
–
gion_13Sep 25 '13 at 20:08

jeerose, why do you have (Math, this) as agruments when Roatin Marth only has (null, this)?
–
HankHNov 3 '09 at 18:26

@HankH: see my response to your comment in a comment to my own answer.
–
Roatin MarthNov 3 '09 at 18:28

1

I don't understand what you mean by "ChaosPandion's solution works if you're using protoype". How is your solution different, except you're using the Math object as the context?
–
Ionuț G. StanNov 3 '09 at 18:28

2

Please explain how mine only works if you use prototype.
–
ChaosPandionNov 3 '09 at 18:28

Sorry, I meant if you extend the prototype yours will work. Apologies.
–
jayNov 3 '09 at 18:31

Is this homework? You need to add a prototype to the array class which defines a function for min and max and then write some code that traverses the array storing the greatest or least value it's found.