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

2 Answers 2

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.

\$\endgroup\$
7
  • \$\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
    Commented Oct 27, 2011 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
    Commented Oct 27, 2011 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\$ Commented Jan 13, 2014 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
    Commented Jan 13, 2014 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\$ Commented Jan 14, 2014 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.

\$\endgroup\$
1
  • \$\begingroup\$ code is for a Chromium extension. It's safe to assume console.log \$\endgroup\$
    – Kai Hendry
    Commented Oct 27, 2011 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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