Question

I am getting several 'undefined' errors when running this code in JSHint:

MERLIN.namespace('MERLIN.http');

MERLIN.http = function ($, window) {
    'use strict';
    // import dependencies

    function request(config) {
        if (!config || typeof config !== 'object') {
            return;
        }
        // perform request
        $.ajax({
            type: config.type || 'GET',
            url: config.url,
            dataType: config.dataType,
            data: config.data || {},
            processData: config.process || false,
            beforeSend: function () {
                indicator(config.panel, config.indicator);
            },
            complete: function () {
                indicator(config.panel, config.indicator);
            },
            success: function (resp) {
                var callback = config.success || null;
                if (typeof callback !== 'function') {
                    callback = false;
                }
                if (callback) {
                    callback.apply(this, [resp]);
                }
            },
            error: function (xhr, textStatus, errorThrown) {
                httpError({
                    xhr: xhr,
                    status: textStatus,
                    error: errorThrown,
                    panel: config.panel
                });
            }
        });
    };

    function indicator(panel, type) {
        if ((!panel || typeof panel !== 'string') || (!type || typeof type !== 'string')) {
            return;
        }
        var indicatorType = (type === 'large') ? type = 'indicatorLarge' : type = 'indicatorSmall';
        return $(panel).toggleClass(indicatorType);
    };

    function httpError() {
        return this;
    };

    return {
        request: request,
        error: httpError
    };

} (jQuery, this);

I am not sure why the undefined errors are being thrown for 'indicator' and 'httpError' and why the use of 'return this' is a potential strict violation. I know I can safely ignore the undefined error relating to the namespace as the general purpose namespace function is defined earlier in a separate file.

Is it just a case of pragmatism versus strict validation?

Thanks :)

Was it helpful?

Solution

Regarding the 'indicator' is not defined. and similar errors: JSHint is derived from JSLint, which was written by Douglas Crockford. Crockford has a thing about calls to functions appearing in the source text before they're defined, even though it's perfectly correct and legal code and there's no ambiguity whatsoever. I actually think this is a case of JSLint (and JSHint when that error is enabled) being actively anti-helpful — I want to know when something is truly undefined, not when it's undefined-according-to-Crockford's-style-rules. (Not that I have an opinion.)

You could avoid those errors by moving the declarations of indicator and httpError up above request, but other than the false errors from JSHint, there's no reason to do so.

Regarding the error on return this;, I believe that's JSLint/JSHint's way of telling you that you're returning the global object, because it expects that functions starting with a lower-case letter are just called as functions and not a pseudo-methods. Why does httpError return this? The way you're calling it, this will be the global object.

So although it's right that you're returning the global object in that case, you can also get that error completely spuriously. For instance, this code produces that error:

var Foo = (function() {
    "use strict";

    function Foo() {

    }
    function bar() {
        return this; // "ERROR: [8:16]: Strict violation."
    }
    Foo.prototype.bar = bar;

    return Foo;
})();

There's no strict violation there whatsoever. bar will return this, which if I call bar correctly (e.g., var f = new Foo(); f.bar();) will be an instance of an object created via Foo, not the global object.

If I change that code so that I don't help my tools help me:

var Foo = (function() {
    "use strict";

    function Foo() {

    }

    Foo.prototype.bar = function() {
        return this;
    };

    return Foo;
})();

...the error goes away, because JSLint/JSHint assume that the function will be called with this set to something other than the global object. But then my functions are anonymous, which is less than ideal.

But you can make JSLint/JSHint happy by making the function name start with something other than a lower-case letter. For instance, my usual naming convention works:

var Foo = (function() {
    "use strict";

    function Foo() {

    }
    function Foo$bar() {
        return this;
    }
    Foo.prototype.bar = Foo$bar;

    return Foo;
})();

No errors generated. The names Foobar, Foo_bar, and $bar all work as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top