3
\$\begingroup\$

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!

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – jfriend00 Oct 27 '11 at 0:22
  • \$\begingroup\$ It's for Chromium, only Chromium \$\endgroup\$ – Kai Hendry Oct 27 '11 at 7:37
8
\$\begingroup\$

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.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Halting execution is not what I want (or anyone else for that matter IMO), I want to continue through to the next loop. \$\endgroup\$ – Kai Hendry Oct 27 '11 at 9:15
  • 3
    \$\begingroup\$ 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) . \$\endgroup\$ – cHao Oct 27 '11 at 9:32
  • \$\begingroup\$ assert does not mean necessary halting the program. It could also mean just logging the error. By the way this is the default behavior in PHP. A good assert function would allow for configuration and do different things in debug mode (die displaying a backtrace) and in a published application (silently log or send feedback to the server). \$\endgroup\$ – Lorenz Meyer Jan 13 '14 at 16:53
  • \$\begingroup\$ @LorenzMeyer: PHP's default behavior is rather broken, IMO, and should not be used or emulated. Fortunately, PHP does let you configure assertions to act as they do in nearly every other environment that supports them. I wish an error or exception were the default behavior, and one had to go out of one's way to misuse them as input validation and other such post-release stuff. \$\endgroup\$ – cHao Jan 13 '14 at 20:23
  • \$\begingroup\$ @chao I agree, an assertion by it's nature is never intended for validation. A failed assertion means a real bug. It deserves a program to halt. But this can be too a too strong reaction. If you debug or test, this is what you want : a plain crash with a stacktrace. Now, disabling assertions for delivery assumes that you tested your app 100% and that you can put your hand in the fire that there's no bug remaining. \$\endgroup\$ – Lorenz Meyer Jan 14 '14 at 5:52
2
\$\begingroup\$

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.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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