lint error on property assignment for js object

3k Views Asked by At

using this pattern lint complains when I set up a new public var(property?) without giving it a default value. Is this bad practice?

//file1.js

/*jslint browser: true, white: true, todo: true */

if( typeof(app) === "undefined" ){ //lint complains here about the "undefined" 
    var app = {};
}

//Self-Executing Anonymous Function (Public & Private)
(function( core, $, undefined ) {

    //private var
    var privateVarValue;

    //public var
    app.core.publicVarValue; //lint complains here (expected assignment or function call)

    app.core.someFunction = function(){
        //do something
    });

}( window.app.core = window.app.core || {}, jQuery ));

//file2.js

/*jslint browser: true, white: true, todo: true */

if( typeof(app) === "undefined" ){ //lint complains here about the "undefined" 
    var app = {};
}

//Self-Executing Anonymous Function (Public & Private)
(function( aModule, $, undefined ) {

    app.aModule .someFunction = function(){

        if(someCondition){
            app.core.publicVarValue = "1";
        }
        else {
            app.core.publicVarValue = "2";
        }
    });

    app.aModule.a = function(){
        //do something
        console.log(app.core.publicVarValue);
    });

    app.aModule.b = function(){

        if(app.core.publicVarValue){

            app.aModule.a();

        } else {
            //the public still hasnt been set, kick back an error
            console.log('an error occurred');
        }
    });

}( window.app.aModule= window.app.aModule || {}, jQuery ));  

Lint doesn't like the publicVarValue to be empty, and it kind of urks me to have to set default values. Can someone tell me how i can both squelch lint and whats the shortest realistic value i can apply to this public var to initialize it, it will be used at a later time.

edit, revised question..

1

There are 1 best solutions below

4
On BEST ANSWER

To be blunt, this code is a bit of a mess (see bulleted stuff, below), and I'm still not sure what the question is, exactly. I'm going to assume it's "how do I lint this code". Here's one way.

Note in my comment, I mean to take your code to JSLint.com and get it to work there without turning on any switches (slap them at the top of your file, as you started to do; that's good). There were still lots of obvious errors in your code, like the extra end parens on each of your function assignments.

[EDIT: Removed code from earlier, replaced with stuff below. If it's useful, you can see the old stuff in the edit history]

So here are some pointers:

  • You've got scoping issues. If you're passing window.app.aModule in as aModule, there's no reason to keep using the global handle app.aModule in your function. (I removed the global context from those references.) EDIT: If you want to do the anonymous closure trick, then 1.) Don't pass in the global and 2.) make sure you have a private var somewhere, or you're wasting the trick!
  • The end paren in function declarations -- I'm going to assume that's a careless error, but if you intend it to do something, what is it?
  • Note that, to keep JSLint happy, you need to use things you define, and define things you use -- params in your function must be used, and variables like someCondition must be defined.
  • Not sure why you had undefined as a parameter in your function -- what was the goal there? ...

EDIT: Okay, I think I get what you're trying to do now; thanks for the blog link. The thing throwing me off is that you weren't taking advantage of the pattern's real advantage, the ability to, "limit access to variables and functions within your closure, essentially making them private and only choosing to expose an API of your choice to the global scope." Everything was attached to aModule in your stuff; there were no "private" variables.

I think you're trying to do something like this...

/*jslint browser: true, white: true, todo: true, sloppy:true */
/*global jQuery */

// No reason to pass in a globally scoped variable if
// you're always accessing it globally. See Dalgleish's
// line where he says `window.baz = baz;` -- `baz` isn't
// passed.
(function($) {
    // Now the way you had this written, it didn't benefit
    // from the pattern. Let's use publicVarValue as a
    // private variable here, just as an example.
    // It's now *only* in this anonymous scope.
    var publicVarValue;

    // Set up the first function on the global module.
    // Note that you never initialized `someCondition`;
    // I'm making it a param
    window.app.aModule.someFunction = function(someCondition){
        if(someCondition){
            publicVarValue = "1";
        }
        else {
            publicVarValue = "2";
        }
    };

    // Set up the second function on the global module.
    window.app.aModule.a = function(){
        //do something
        $("#someId").append("Value is: " + publicVarValue + "<br />");
    };

    // Now we set up the function contingent on publicVarValue
    // being set.
    window.app.aModule.b = function(){
        if (publicVarValue) {
            window.app.aModule.a();
        } else {
            //the public still hasnt been set, kick back an error
            window.console.log('an error occurred');
        }
    };
}(jQuery));

So that follows the anonymous function scoping pattern and JSLints without issue.

That make more sense? No reason to pass in a handle to a global, still not sure why you had undefined for a param, but otherwise, this is what the pattern you linked suggests doing.

My biggest suspicion, though, is that you want publicVarValue to be, um, public. I'm not sure why -- if you don't really need to expose that, then the above is your code using the pattern Dalgleish describes.

Closer?


Btw, I don't get when Dalgleish suggests...

A technique you can see used within jQuery itself is to reference an extra parameter that isn’t defined when the anonymous function is executed, in effect creating an alias for ‘undefined’:

Check this code:

function wacky(p1, undefined)
{
    if (p1 === undefined)
        window.alert('undef');
    else
        window.alert('not undef');
}

var var1;
// var1 is undefined. It works.
wacky(var1); // undef

// Now you have a truthy value saying it's undefined.
// Wack.
wacky("spam", "spam");  // undef?

// Just to round out possibilities -- now
// truthy is not truthy. I'm not even sure
// what we're checking any more.  ;^)
wacky("spam", "not spam");  // not undef?

I can't see any reason to open undefined up for being overwritten like that. I understand the motivation, I think -- if you always pass the right number of parameters, then undefined will have no associated parameter and will be, in a manner of speaking, always set to undefined. You'd be more defensive, I think, to say...

function wacky(p1)
{
   var spam;
   undefined = spam;
   //...
}

Or, as this answer suggests, use void 0 to get a clean undefined.

But that might be absolutely superfluous. When I try to set undefined on a global scope to something in Chrome right now, it won't let me, afaict. Check this fiddle (lots of alerts; sorry).

So I'm buying what this guy is selling. Don't do the undefined parameter trick. If you ever accidentally call a function with an extra parameter, you're entering a world of pain, Smokey.