0

For a new project I need to write a JavaScript library and I'm not sure how to structure it. I read many articles and questions here on stackoverflow yesterday.

I like to support public and private functions and classes. So here is my result:

(function(window) {

    var Library = Library || {};

    // Library namespace
    Library = (function() {
        function privateFunc() {
            return "I'm a private functon in Library.";
        }
        var privateClass = function(param) {
            var _param = param;    
        }
        return {
            constructor: Library,
            publicFunc: function() {
                return "I'm a publicFunc functon in Library.";
            }
        };
    })();

    // String namespace
    _namespace('String');
    Library.String = (function() {
        function privateFunc() {
            return "I'm a private functon in Library.String.";
        }
        return {
            constructor: Library.String,
            publicFunc: function() {
                return "I'm a publicFunc functon in Library.String.";  
            },
            publicClass: function(param) {
                var _param = param;
            }
        };
    })();

    // global function
    function _namespace(name) {
        ...
    }

    // register libary
    window.Library= window.$L = Library;

})(window);

Is this a good way to structure a library or are there better ways? And how do I implement private and public functions for my privateClass/publicClass?

Thank you

Torben
  • 1,290
  • 5
  • 22
  • 41
  • 1
    There are other javascript frameworks that can do this for you, such as jQuery, mootools, prototype, etc. If you really want to do this yourself, why don't you have a look in their codebase? – Spoike Jun 15 '11 at 06:41
  • read [`underscore`](http://documentcloud.github.com/underscore/docs/underscore.html). Use that structure. – Raynos Jun 15 '11 at 06:45
  • @Spoike do _what_ for him? He's writing an arbitary library and wants to know how to structure his file. jQuery, Mootools, prototype, etc are not going to help him – Raynos Jun 15 '11 at 06:47
  • 1
    @Spoike Yes, we're using jQuery too. I don't want to write my own framework but structure my own JavaScript code. @Raynos You're right and thank you for the link. – Torben Jun 15 '11 at 06:48
  • @Raynos: Handling of classes and whatnot is available in these. And I'm just saying as a tip that if you're writing an arbitrary library then you should read up on how other frameworks do it. There are lots of them, just take your pick. :-) – Spoike Jun 15 '11 at 06:50
  • @Spoike I already take a look at the jQuery source code, but jQuery for example has a really flat structure I think? – Torben Jun 15 '11 at 06:52
  • @Torben H: [Is there a better way to create an object-oriented class with jquery?](http://stackoverflow.com/q/84716/3713) – Spoike Jun 15 '11 at 06:55
  • @Torben H: Also, you might want to check out how to do plug-ins in jQuery (and solve your problems by building a plugin instead). – Spoike Jun 15 '11 at 06:58
  • [Recent question about OOP js](http://stackoverflow.com/questions/6337879/oop-programming-in-javascript-with-node-js/6339819#6339819) [Plugin structure](http://stackoverflow.com/questions/5980194/jquery-plugin-template-best-practice-convention-performance-and-memory-impact/6272580#6272580) – Raynos Jun 15 '11 at 07:16
  • @Spoike jQuery has no notion of class. MooTools has a wrapper and so does prototype. but those classical class emulations are the devil! @Spoike Ew hard-coupling to jQuery. – Raynos Jun 15 '11 at 07:18
  • @Raynos: I'm not using jQuery, the op (Torben) mentioned they're using jQuery. – Spoike Jun 15 '11 at 07:52

2 Answers2

2

There is no notion of private / public functions in javascript. By convention functions that start with underscore are considered private.

Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • 3
    not really true: `function(){ var privateFn = function(){}; }` –  Jun 15 '11 at 06:43
  • Yes but you can use functions within "classes" like cwolves example, so they are not accessible from outside the class. – Torben Jun 15 '11 at 06:55
  • 1
    @cwolves You seem to be confusing `local` and `scope` with some generic concept of privacy that doesn't exist in this language. – Raynos Jun 15 '11 at 07:15
  • @Raynos - I'm not confusing the two, I'm saying that my example ___acts___ like a private function. And if it looks like a duck, sounds like a duck and acts like a duck... –  Jun 15 '11 at 07:16
  • @cwolves there's nothing private about it. [The instance variables in strawman are private](http://wiki.ecmascript.org/doku.php?id=strawman:instance_variables). there is a clear distinction between closures and local variables and private data bound to an object. – Raynos Jun 15 '11 at 07:20
  • define "private" : "Only accessible from within the class". Care to explain how it's ___not___ private? Just because it doesn't actually use the word "private"? My point is that you can ___emulate___ private methods and properties perfectly well using JavaScript. –  Jun 15 '11 at 07:23
  • Using your own example: `function cls(){ var secret = 42; return { get secret(){ return secret; } }; }` There is no ___functional___ difference between having the data bound to the actual object or having it bound using a closure. –  Jun 15 '11 at 07:28
  • @cwolves but "private" is a word merely used for those familiar with other languages. It's merely local and you have exposed access through closures and scope chain. Just because everyone mis-uses the word private does not mean that it's the correct terminology. – Raynos Jun 15 '11 at 07:31
  • My point is that it functions ___exactly___ the same and if someone asks "how do I make a private variable in JS", I don't see what the point is in saying "private variables don't exist" when something does exist that acts the ___same___ –  Jun 15 '11 at 07:35
  • @cwolves that's a different matter. I think both attitudes are correct. Pedantry about wrong terminology and pragmatism. You must also realise that those "private" variables are bound to methods not instances right. You can't use `obj.method.apply(otherObj)` and magically use the otherObj's private variables. (which you can with instance variables in strawman because they are _private_) – Raynos Jun 15 '11 at 07:37
  • um, they're bound to instances since they're declared in the constructor. And whether or not `obj.method.apply(otherObj)` should even work... The whole point of private variables is that there is no way to access them from outside of the ___pre-defined___ methods. If there's a work-around to that, I'd say they're ___less___ private than declaring variables in the constructor. –  Jun 15 '11 at 07:41
  • @cwolves actually they are more private because you can't inject `eval` to read the variables. – Raynos Jun 15 '11 at 07:51
  • @Raynos - have an example of that? And per your prior example, wouldn't `(function(){ alert(this.secret);}).apply(otherObj)` read the private variable? –  Jun 15 '11 at 07:52
  • @cwolves I'm mentioning that `@secret` which is an instance variable that _might_ be in ES6 but is just speculation would be the only way to have private variables. And the [`eval` hack](http://ejohn.org/blog/eval-kerfuffle/) – Raynos Jun 15 '11 at 07:55
  • Yeah, I thought it would probably be something along those lines (re: eval hack), but Mozilla was the only browser to support the scope argument and they removed it. –  Jun 15 '11 at 07:57
  • @cwolves doesn't me I don't have a copy of a browser with the eval hack lying around ;) – Raynos Jun 15 '11 at 09:06
0

Just to mess with Raynos (I wrote this years ago):

Private, Public and Static variables

The way that we define variables in our Objects determines what methods our Objects have available to access those variables. In JavaScript, there are five levels of methods and properties when working with OO code.

  • Private Declared with 'var variableName' or 'function functionName' inside of the object. Can only be accessed by other private or privileged functions.

  • Public Declared with 'this.variableName' inside of the object. Can be changed by any function or method.

  • Privileged Declared with 'this.functionName = function(){ ... }' inside of the object. Can be accessed by any function or method and can call reference or change any Private variable.

  • Prototype Declare with 'Class.prototype.variableName' or 'Class.prototype.functionName'. Functions declared this way will have access to any public or prototype variables. Attempts to change variable created this way will instead create a new public variable on the object and the prototype variable will be unavailable.

  • Static Declare with 'Class.variableName' or 'Class.functionName'. Can be changed by any function or method. This method is rarely used. To understand these different levels, let's look at an example:


function Cat(name, color){

    /*
    Constructor: any code in here is run when the object is created
    */
    Cat.cats++;

    /*
    Private variables and functions - may only be accessed by private or privileged functions.

    Note that 'name' and 'color', passed into the Class, are already private variables.
    */
    var age  = 0;
    var legs = 4;
    function growOlder(){
        age++;
    }

    /*
    Public variables - may be accessed publicly or privately
    */
    this.weight = 1;
    this.length = 5;

    /*
    Privileged functions - may be accessed publicly or privately
    May access Private variables.

    Can NOT be changed, only replaced with public versions
    */
    this.age = function(){
        if(age==0) this.length+=20;

        growOlder();
        this.weight++;
    }
}

/*
Prototyped Functions - may be accessed publicly
*/
Cat.prototype = {
    talk:     function(){ alert('Meow!'); },
    callOver: function(){ alert(this.name+' ignores you'); },
    pet:      function(){ alert('Pet!'); }
}

/*
Prototyped Variables - may be accessed publicly.
May not be overridden, only replaced with a public version
*/
Cat.prototype.species = 'Cat';

/*
Static variables and functions - may be accessed publicly
*/
Cat.cats = 0;
  • Ew. Wrong terminology. So 2005. Stop bringing Java into my JavaScript! Seriously though we're not actually answering his question and just having a noise argument. – Raynos Jun 15 '11 at 07:40
  • Yeah, well I wrote this in 2005 I think :) –  Jun 15 '11 at 07:44