1

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..

blamb
  • 4,220
  • 4
  • 32
  • 50
  • What do you mean by "initiate"? Either you initialise/create it by assigning a value, or you dont. – Bergi Nov 18 '14 at 00:11
  • shouldnt it be typeof app ?? – Santiago Rebella Nov 18 '14 at 00:13
  • 2
    Accessing/referring-to the property as you do has no effect in JavaScript, unless you're using a compiler like Closure which interprets it in some way. If you want the property to exist, but don't want to give it a specific value yet, you need to explicitly define it `= undefined` (although in most cases `= null` would probably be used instead). – Jeremy Nov 18 '14 at 00:15
  • Can't really tell what you're asking from this code. First, it'd be great if you'd take the time to get the rest of your code to lint. I've got a very quick guess [here on pastebin](http://pastebin.com/Ujr6pQAq). Then I'm left wondering, as Jeremy mentions, what you're trying to do with `app.core.publicVarValue;`. I'm afraid your faux-code isn't doing a very good job describing your practical issue. – ruffin Nov 18 '14 at 01:00
  • btw, to fix the error in the first line, use `if (app === undefined) {`, or, possibly, `if (app === undefined || app === null) {` – ruffin Nov 18 '14 at 01:02
  • i meant initialise, sorry. i was thinking that giving it no value it was still initializing. Ok, i just want to establish it, undefined. i like the undefined solution better than null, but i would prefer to use nothing, so that the property definitions just contain empty properties (like in php) and those properties will be populated later in the code. @ruffin, its just a lint question for initializing a property for later use. the sky is the limit as far as how you want to assign a value to it later. and yes, `app === undefined looks better` – blamb Nov 18 '14 at 01:26
  • so question, is it standard practice to just define it first? i think its alot cleaner just to see a clean list of empty properties on the top of the script file, and set them later. if so, then ill guess thats where im going wrong, and the cleaner solution will just throw off lint testing. – blamb Nov 18 '14 at 02:00

1 Answers1

1

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.

Community
  • 1
  • 1
ruffin
  • 16,507
  • 9
  • 88
  • 138
  • yes, your assumptions are correct about coming from another language, that being PHP. It is amazing how far the question has stretched though, that code was pseudo, albeit bad i guess. i think the question was more based on the fact that this design pattern is designed to have the equivalent of in php setting up properties inside a class where the functions serve as the methods. Im just asking if i can set my properties at the beginning of a code page at the top of the script – blamb Nov 19 '14 at 20:23
  • im going for the mark dalgleish http://markdalgleish.com/2011/03/self-executing-anonymous-functions/ pattern here mostly, and trying to just set up empty public vars on the top of each script for use by convention. whats the best way to code that out where lint will accept. see my original example. i want to stress, my last comment got cut off, "empty", i would like to set type up simple, short, sweet, and empty like this `//public var` `app.core.somethingWillBe;` – blamb Nov 19 '14 at 20:49
  • here is another example, http://programmers.stackexchange.com/questions/128734/self-executing-anonymous-function-vs-prototype however i cant find an example the way im trying to do it by just initializing them empty, is this illegal? the reason i might want to do this is because i dont want to have to set these specific paramaters values at this point, i want to simply initaliaze them the simplest way, to remind the coder that they exist, a place of central registry if you will, and i wanted to do it shortcode, as opposed to having to assign it a value right now. – blamb Nov 19 '14 at 20:56
  • Yeah it does thanks. I see what you mean now. On another point, per your quote `there's no reason to keep using the global handle app.aModule in your function.` for me it became increasingly easier to find pieces across 20 files in jet brains so i started using the main object.subobject for easy searc and so my app could look cool. lol – blamb Nov 20 '14 at 21:27