external/bbop.js
function _is_same(a, b){
	//bark('typeof(a, b): ' + typeof(a) + ',' + typeof(b));

	var ret = false;
	if( a == b ){ // atoms, incl. null and 'string'
	    //bark('true on equal atoms: ' + a + '<>' + b);
	    ret = true;
	}else{ // is list or obj (ignore func)
	    if( typeof(a) === 'object' && typeof(b) === 'object' ){
		//bark('...are objects');
		
		// Null is an object, but not like the others.
		if( a == null || b == null ){
		    ret = false;
		}else if( Array.isArray(a) && Array.isArray(b) ){ // array equiv
		    //bark('...are arrays');
		    
		    // Recursively check array equiv.
		    if( a.length == b.length ){
			if( a.length == 0 ){
			    //bark('true on 0 length array');
			    ret = true;
			}else{
			    ret = true; // assume true until false here
			    for( var i = 0; i < a.length; i++ ){
				if( ! _is_same(a[i], b[i]) ){
				    //bark('false on diff @ index: ' + i);
				    ret = false;
				    break;
				}
			    }
			}
		    }

		}else{ // object equiv.

		    // Get unique set of keys.
		    var a_keys = Object.keys(a);
		    var b_keys = Object.keys(b);
		    var keys = a_keys.concat(b_keys.filter(function(it){
			return a_keys.indexOf(it) < 0;
		    }));
		    
		    // Assume true until false.
		    ret = true;
		    for( var j = 0; j < keys.length; j++ ){ // no forEach - break
			var k = keys[j];
			if( ! _is_same(a[k], b[k]) ){
			    //bark('false on key: ' + k);
			    ret = false;
			    break;
			}
		    }
		}
	    }else{
		//bark('false by default');
	    }
	}
	
	return ret;
    }
function _is_same(a, b){
	//bark('typeof(a, b): ' + typeof(a) + ',' + typeof(b));

	var ret = false;
	if( a == b ){ // atoms, incl. null and 'string'
	    //bark('true on equal atoms: ' + a + '<>' + b);
	    ret = true;
	}else{ // is list or obj (ignore func)
	    if( typeof(a) === 'object' && typeof(b) === 'object' ){
		//bark('...are objects');
		
		// Null is an object, but not like the others.
		if( a == null || b == null ){
		    ret = false;
		}else if( Array.isArray(a) && Array.isArray(b) ){ // array equiv
		    //bark('...are arrays');
		    
		    // Recursively check array equiv.
		    if( a.length == b.length ){
			if( a.length == 0 ){
			    //bark('true on 0 length array');
			    ret = true;
			}else{
			    ret = true; // assume true until false here
			    for( var i = 0; i < a.length; i++ ){
				if( ! _is_same(a[i], b[i]) ){
				    //bark('false on diff @ index: ' + i);
				    ret = false;
				    break;
				}
			    }
			}
		    }

		}else{ // object equiv.

		    // Get unique set of keys.
		    var a_keys = Object.keys(a);
		    var b_keys = Object.keys(b);
		    var keys = a_keys.concat(b_keys.filter(function(it){
			return a_keys.indexOf(it) < 0;
		    }));
		    
		    // Assume true until false.
		    ret = true;
		    for( var j = 0; j < keys.length; j++ ){ // no forEach - break
			var k = keys[j];
			if( ! _is_same(a[k], b[k]) ){
			    //bark('false on key: ' + k);
			    ret = false;
			    break;
			}
		    }
		}
	    }else{
		//bark('false by default');
	    }
	}
	
	return ret;
    }
function _is_same ( a , b ) { //bark('typeof(a, b): ' + typeof(a) + ',' + typeof(b)); var ret = false ; if ( a == b ) { // atoms, incl. null and 'string' //bark('true on equal atoms: ' + a + '<>' + b); ret = true ; } else { // is list or obj (ignore func) if ( typeof ( a ) === 'object' && typeof ( b ) === 'object' ) { //bark('...are objects'); // Null is an object, but not like the others. if ( a == null || b == null ) { ret = false ; } else if ( Array . isArray ( a ) && Array . isArray ( b ) ) { // array equiv //bark('...are arrays'); // Recursively check array equiv. if ( a . length == b . length ) { if ( a . length == 0 ) { //bark('true on 0 length array'); ret = true ; } else { ret = true ; // assume true until false here for ( var i = 0 ; i < a . length ; i ++ ) { if ( ! _is_same ( a [ i ] , b [ i ] ) ) { //bark('false on diff @ index: ' + i); ret = false ; break ; } } } } } else { // object equiv. // Get unique set of keys. var a_keys = Object . keys ( a ) ; var b_keys = Object . keys ( b ) ; var keys = a_keys . concat ( b_keys . filter ( function ( it ) { return a_keys . indexOf ( it ) < 0 ; } ) ) ; // Assume true until false. ret = true ; for ( var j = 0 ; j < keys . length ; j ++ ) { // no forEach - break var k = keys [ j ] ; if ( ! _is_same ( a [ k ] , b [ k ] ) ) { //bark('false on key: ' + k); ret = false ; break ; } } } } else { //bark('false by default'); } } return ret ; }
Better general comparison function.
Better general comparison function .