I need to compare some values of a Javascript object. If they fail to be identical, I want to pretty print to console.log the mismatch.

The initial code I have written which I find fugly after a JS beautify looks like:

function assert(a, b, message) {
if (a != b) {
    console.log("Failed to match " + message + " " + a + " != " + b);
    return false;
}
return true;
}


    if (!assert(parsedInput.protocol, cu.protocol, "protocol")) {
        continue;
    }
    if (!assert(parsedInput.port, cu.port, "port")) {
        continue;
    }
    if (!assert(parsedInput.hostname, cu.hostname, "hostname")) {
        continue;
    }
    if (!assert(parsedInput.hash, cu.hash, "hash")) {
        continue;
    }

Please tell me I've missed the plot and I could write this a lot better. Feel free to critique the rest of the code. Thank you!

share|improve this question
Keep in mind that console.log does not exist in some versions of IE when not running the IE debugger. So, you should not ever be accessing console.log in your regular production code. – jfriend00 Oct 27 '11 at 0:22
It's for Chromium, only Chromium – Kai Hendry Oct 27 '11 at 7:37

2 Answers

up vote 4 down vote accepted

I (and many other people) expect certain behavior from a function called "assert"...namely that it throws an exception or otherwise halts execution if the asserted condition isn't true. If your assert function did that, you wouldn't have to test the return value.

function assertEqual(a, b, message)
{
    if (a != b) throw new Error(message + " mismatch: " + a + " != " + b);
}

assertEqual(parsedInput.protocol, cu.protocol, "protocol");
assertEqual(parsedInput.port,     cu.port,     "port");
assertEqual(parsedInput.hostname, cu.hostname, "hostname");
assertEqual(parsedInput.hash,     cu.hash,     "hash");

If that's not what you want, then you should seriously consider renaming your function. Maybe check or something, i dunno. Assertions die when they're false.


Now, as for your equality tests, you could do something like

function propsEqual(obj1, obj2, propNames) {
    var result = true;
    for (var i = 0; i < propNames.length; ++i) {
        var prop = propNames[i];
        if (obj1[prop] != obj2[prop]) {
            console.log("Failed to match " + prop +": " + obj1[prop] + " != " + obj2[prop]);
            result = false;
        }
    }
    return result;
}

if (!propsEqual(parsedInput, cu, ["protocol", "port", "hostname", "hash"])) {
    console.log("Skipping.");
    continue;
}

Benefits of this approach being, you get to see all of what doesn't match, rather than stopping at the first thing.

share|improve this answer
Halting execution is not what I want (or anyone else for that matter IMO), I want to continue through to the next loop. – Kai Hendry Oct 27 '11 at 9:15
1  
Then for other people's sake, rename your function. The name assert carries with it some expectations, and what you want apparently doesn't fit with those expectations at all. See en.wikipedia.org/wiki/Assertion_(computing) . – cHao Oct 27 '11 at 9:32

You could write it as:

function safeLog(s) {
    if (window.console && window.console.log) {
        console.log(s);
    }
}

function assert(a, b, message) {
    if (a != b) {
        safeLog("Failed to match " + message + " " + a + " != " + b);
        return false;
    }
    return true;
}

if (!assert(parsedInput.protocol, cu.protocol, "protocol") ||
  !assert(parsedInput.port, cu.port, "port") ||
  !assert(parsedInput.hostname, cu.hostname, "hostname") ||
  !assert(parsedInput.hash, cu.hash, "hash")) {
    continue;
}

This would condense the comparisons into one logic statement and would protect from the cases in IE where console.log doesn't exist.

share|improve this answer
code is for a Chromium extension. It's safe to assume console.log – Kai Hendry Oct 27 '11 at 9:15

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.