Object Setter demo (mean, median, mode and range)

See http://stackoverflow.com/a/26187126/1683264 for an explanation.

by Steve Church

HTML

Data: <span id="data"></span><br>
Mean: <span id="mean"></span><br>
Median: <span id="median"></span><br>
Mode: <span id="mode"></span><br>
Range: <span id="range"></span>

CSS

span { color: purple; font-weight: bold; font-family: Courier}

JavaScript

function $(id) { return document.getElementById(id); }
function out(what,where) { $(where).innerHTML = what; }

var avg = {
    // Declaring these items is not necessary.  It just helps you
    // remember what public values are set by the "dataset" setter
    data: [],
    mean: null,
    median: null,
    mode: [],
    range: null,
    
    // Object setter
	set dataset(arr) {
		var isArray = function(obj) {return (Object.prototype.toString.call(obj) === '[object Array]')};
		var isNumber = function(n) {return !isNaN(parseFloat(n)) && isFinite(n)};

		// sanity checking
		if (!isArray(arr)) throw '"' + arr + '" is not an array.';
		for (var i=0; i<arr.length; i++) {
			if (!isNumber(arr[i])) throw '"' + arr[i] + '" is not a number.';
            arr[i]*=1; // if numeric string, convert to number
		}

		// data (array)
		this.data = arr.sort(function(a,b){return a-b});
    
		// mean (float)
        this.mean=0;
		for (var i=0; i<arr.length; i++) {
			this.mean += arr[i];
		}
		this.mean /= arr.length;

		// median (float)
        this.median = arr[Math.ceil(arr.length / 2) - 1];
		// if even number of values, average the 2 middle numbers
        if (!(arr.length % 2)) {
            this.median = (this.median + arr[arr.length / 2]) / 2;
        }
		
		// mode (array)
		var leader = {num:[],freq:0}, contender = {num:null,freq:0};
		for (var i=0; i<arr.length; i++) {
			if (contender.num === arr[i]) contender.freq++;
			else {
				contender.num = arr[i];
				contender.freq = 1;
			}
			if (contender.freq == leader.freq) {
                leader.num.push(contender.num);
			}
			else if (contender.freq > leader.freq) {
				leader.freq = contender.freq;
				leader.num = [contender.num];
			}
		}
		this.mode = (leader.freq > 1) ? leader.num : [];
		
		// range (float)
		this.range = arr[arr.length - 1] - arr[0];

	} // end dataset object setter
} // end avg object

try {
    // call setter to populate object properties
    avg.dataset =...