Most elegant way to define private "class" functions in Spine - javascript

I'm currently diving into Spine and I'm currently asking myself what would be the most elegant way to define a private function, using Spine's class creation method.
var PrinterManager = Spine.Class.create({
init: function () {
},
getAllAvailablePrinters: function () {
},
printDocument: function () {
}
});
(function () {
var instantiateActiveX = function(){
console.log("...");
}
PrinterManager.include({
pubInitActiveXPrinter: function(){
instantiateActiveX();
}
});
})();
As you can see I want instantiateActiveX to be private and not visible to the outside. Using the JavaScript closure function trick, I can make it private without any problems, but this solution doesn't seem too elegant to me in the contest of creating classes like Spine does.
The code works, i.e. I can call PrinterManager.init().pubInitActiveXPrinter() which will then internally call the private function and - correctly - I cannot call PrinterManager.init().instantiateActiveX().
My Question - Is there a more elegant way to do it with Spine that I didn't yet discover??

Well to put it simple, there's no way other than closures to make some function/variable invisible/private from the global scope.

No.
"private" functions don't exist. You only have local functions and closure state. And using local functions/variables and closures for state does not mix well with using prototypical inheritance.
The real question you should be asking is "why do you need private functions" because you don't.
If a function is unstable and shouldn't be used because the API might change just prepend it with _
var PrinterManager = {
...
_instantiateActiveX: function() {
...
}
}
If anyone uses these internal functions or variables then they have no right to complain when their code breaks if you change it.

Related

What's the difference between these namespacing methods?

I'm new to JavaScript and am trying to understand how to use namespaces to avoid naming conflicts. So far, the two most popular methods I've found for creating namespaces are these:
Method 1:
var MYAPPLICATION = {
calculateVat: function (base) {
return base * 1.21;
},
product: function (price) {
this.price = price;
this.getPrice = function(){
return this.price;
};
},
doCalculations: function () {
var p = new MYAPPLICATION.product(100);
alert(this.calculateVat(p.getPrice()));
}
}
Method 2:
var DED = (function() {
var private_var;
function private_method()
{
// do stuff here
}
return {
method_1 : function()
{
// do stuff here
},
method_2 : function()
{
// do stuff here
}
};
})();
Is the difference that the second method allows you to have private methods and variables, since only what is inside of the object being returned will be globally accessible? Which of these methods is best (or is there a better way)?
If you write an API for other people, I think method two is better. Example:jQuery.
In a web page, I prefer method one. Example:stackoverflow
In method two, you can not read and write functions and variables that is private, so if there is a bug, you can not read something by developer-tools for debug.
Second method is called 'module' pattern. Makes it comfortable for developers to use your code. Self-invoking function creates scope, so you only expose methods that you want to make public by returning object that contains references to those methods (public API). Those methods can have a lot of private helper functions and variables that you keep private for your own use. Most of the libraries are written this way. It's generally good to structure your library like that.
Here's a link to the website that explains it well : http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
First method is just the way to put all the related functions together. You can make those for personal use in your module. Example:
Calc.add(5,5), Calc.subtract(3,2), Calc.multiply(3,3);
add, subtract, multiply share same namespace because they are related.

Javascript: which function structure to use

I was reading an article about Javascript's best practices, and kinda got confused about which function structure to use...
I guess it might have an impact on the scope of the variables and functions, but which one of these structures would you use (and which is considered the best practice)?
Structure 1: use the object literals.
var obj1 = {
_myvar : 'myval',
init: function() {
this.function1();
this.function2();
},
function1: function() {
alert('function1');
},
function2: function() {
alert('function2');
}
};
obj1.init();
Structure 2: Wrap the code in an auto-executing function.
(function(){
var _myvar = 'myval',
function1 = function() {
alert('function1');
},
function2 = function() {
alert('function2');
},
init = (function() {
function1();
function2();
}) ();
}) ();
You use the self-executing anonymous function when you don't want others to interfere with your code and/or don't want to use any global variable. If you might want to use those functions/objects/whatever somewhere else, you would want to use the first one.
"Structure 1" is appropriate when you need access to the methods and variables in an object from other parts of your code. That format should always be your preference when you're writing library code that's meant to be reused elsewhere.
"Structure 2" is appropriate when you don't want to share your code with other parts of the application, and so you want to protect the variables and functions from any interference from elsewhere.
I have found Christian Heilmann's Revealing Module Pattern to be quite useful. (Scroll down to the last "green screen" code sample on his page.)
With is pattern, you can create all of your methods/functions privately in an anonymously executed function and then choose your public interface via the returned object.

Defining Functions In Javascript Within jQuery

I'm working on a proprietary site, and I'm having some issues. I'm using jQuery along with prototype, and I've got it namespaced properly, so in this question assume you can use $ or jQ as a namespaced reference to jQuery.
So I've got a bunch of functions, some mix jQuery and javascript, some plain javascript, some jQuery only. Now, currently some functions are defined within the document.ready jQuery function, and some are defined outside of it, kind of like this:
jQ(document.ready(function($) {
if ( ifConfig ) {
//page check, function calls here
fnc1();
fnc2();
fnc3();
fnc4();
}
function fnc1() {
//fnc code in here
}
function fnc2() {
//fnc code in here
}
}); //end document.ready
function fnc3() {
}
function fnc4() {
}
Now this is all pseudo code, you can assume the functions are valid and have valid code in them. Recently I was doing some debugging, and one of my functions that was declared and called inside the document.ready said it was undefined. I moved it outside of the document.ready, and everything worked again.
I'm basically trying to understand the order of how functions are initiated/called better, so my question is when do you declare functions inside the document.ready and when do you declare them outside? Do you only declare inside when they're called within that document.ready only? Or should I always just declare them outside of that document.ready?
Thanks.
Generally, you should declare & define your own namespace, where all of your application logic (including functions/methods) is located. That way you avoid collision with other scripts on your site + that way your code is much cleaner and easier to maintenaine.
var myapp = function(){
var foobar1 = null,
foobar2 = null,
foobar3 = null;
return {
getFoobar1: function(){
return foobar1;
},
getFoobar2: function(){
return foobar2;
},
setFoobar1: function(foo){
foobar1 = foo;
},
clickhandler: function(e){
alert('I am an event handler, and I am not anonymous');
}
// etc.
};
};
$(document).ready(function(){
var Application = myapp();
Application.getFoobar2();
$(document).bind('click', Application.clickhandler);
});
That pattern (some call it the "method pattern") creates a closured function/object which also guarantees private member variables within your namespace, only accessible through the getter functions from the outside.
This is really only a pretty basic example, you can push this idea & pattern to an extend, which is very nice & a good thing (IMO).
A great book about this stuff which was named and recommended pretty often is "Javascript: The Good Parts" by Douglas Crockford.
If a function is only used inside the document ready function, then declare it inside so you don't pollute the global scope. Otherwise, declare it outside so it the rest of your script has access to those functions.
(document).ready is more used for things that need to be executed at page load, and not function declarations. If you declare them inside of (document).ready, their scope will be local to that block - if they're only used locally, that's fine and they should be declared there. Otherwise, declare them outside.
So in your example, if the functions are only used in that block, they should be declared in there. If they're used other places additionally, they should be declared outside.

jQuery plugin design pattern (common practice?) for dealing with private functions [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I've been developing jQuery plugins for quite some time now, and I like to think I know how to design one well by now. One issue keeps nagging me though, and that is how to deal with private functions in a powerful yet elegant manner.
My plugins generally look something like this:
(function($) {
$.fn.myplugin = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'green');
...
};
$.fn.mypluginAnotherPublicMethod = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'red');
...
};
}(jQuery));
Now my question is: how to neatly DRY up that shared functionality? An obvious solution would be to put it in a function within the plugin's namespace:
var fill = function($obj, color) {
$obj.css('background-color', color);
};
Although this solution is effective and nicely namespaced, I really dislike it. For one simple reason: I have to pass it the jQuery object. I.e. I have to call it like this: fill(this, 'red');, while I would like to call it like this: this.fill('red');
Of course we could achieve this result by simply putting fill into jQuery.fn. But that feels very uncomfortable. Imagine having ten plugins developed based on this approach and each plugin putting five of those 'private' functions into the jQuery function namespace. It ends up in a big mess. We could mitigate by prefixing each of these functions with the name of the plugin they belong to, but that doesn't really make it more attractive. These functions are supposed to be private to the plugin, so we do not want to expose them to the outside world at all (at least not directly).
So there's my question: does anyone of you have suggestions for how to get the best of both worlds. That is; plugin code being able to call 'private' plugin functions in a way similar to this.fill('red') (or this.myplugin.fill('red') or even this.myplugin().fill('red') etc.), while preventing jQuery function namespace pollution. And of course it should be light-weight, as these private functions might be called very frequently.
UPDATE: Thanks for your suggestions.
I especially like David's idea of defining an object type that holds the 'private' functions and wraps a jQuery object. The only problem with it is that it still disallows me from chaining 'private' and 'public' functions. Which was big reason to want a syntax like this.fill('red') to begin with.
I ended up with a solution which I consider not tremendously elegant, but appealing to the 'best of both worlds' cause:
$.fn.chain = function(func) {
return func.apply(this, Array.prototype.slice.call(arguments, 1));
};
Which allows for constructs like:
this.
find('.acertainclass').
chain(fill, 'red').
click(function() {
alert("I'm red");
});
I cross-posted my question in other places, which also collected some interesting responses:
http://forum.jquery.com/topic/jquery-plugin-design-pattern-common-practice-for-dealing-with-private-functions
http://groups.google.com/group/jquery-en/browse_thread/thread/fa8ccef21ccc589a
One thing first: if you would like to call something like this.fill('red'); where this is an instance of jQuery, you have to extend the jQuery prototype and make fill() "public". jQuery provides guidelines for extending it's prototype using so called "plugins" that can be added using $.fn.fill, which is the same as jQuery.prototype.fill.
In jQuery callbacks, this is often a reference to the HTML Element, and you can't add prototypes to those (yet). That is one of the reason why jQuery wraps elements and return jQuery instances that can be easily extended.
Using the (function(){})(); syntax, you can create and execute "private" javascript on the fly, and it all disappears when it's done. Using this technique, you can create your own jQuery-like syntax that wraps jQuery into your own private chainable object.
(function(){
var P = function(elem) {
return new Private(elem);
};
var Private = function(elem) {
this.elem = jQuery(elem);
}
Private.prototype = {
elem: null,
fill: function(col) {
this.elem.css('background',col);
return this;
},
color: function(col) {
this.elem.css('color', col);
return this;
}
}
$.fn.myplugin = function() {
P(this).fill('red');
};
$.fn.myotherplugin = function() {
P(this).fill('yellow').color('green');
};
})();
$('.foo').myplugin();
$('.bar').myotherplugin();
console.log(typeof P === 'undefined') // should print 'true'
This way, the P stands for your own toolbox of "private" functions. They won't be available anywhere else in the code or in the jQuery namespace unless you attach them somewhere. You can add as many methods as you like in the Private object, and as long as you return this, you can also chain them jQuery-style as I did in the example.
How about (within the plugin's scope):
var fill = function ()
{
(function (color)
{
this.css ('backgrorund-color', color);
//.. your stuff here ...
}).apply (this, arguments);
}
$.fn.myplugin = function ()
{
fill ('green');
}
That way, fill will retain the jQuery context you're in, and is still private to your plugin
Amended: the above is incorrect w.r.t. scoping, Try the following instead:
var fill = function (color)
{
if (!$this) return; // break if not within correct context
$this.css ('backgrorund-color', color);
//.. your stuff here ...
}
$.fn.myplugin = function ()
{
var $this = $(this); // local ref to current context
fill ('green');
}
You might want to take a look at how the jQuery UI Widget Factory is implemented.
The basic approach is like this:
(function($){
$.fn.myplugin = function(method)
{
if (mp[method]) // map $('foo').myplugin('bar', 'baz') to mp.bar('baz')
{
return mp[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
else if (typeof method === 'object' || ! method)
{
return mp.init.apply(this, arguments); // if called without arguments, init
}
else
{
$.error('Method ' + method + ' does not exist on $.myplugin');
}
};
// private methods, internally accessible via this.foo, this.bar
var foo = function() { … };
var bar = function() { … };
var private = { // alternative approach to private methods, accessible via this.private.foo
foo : function() { … },
bar : function() { … }
}
var mp = { // public methods, externally accessible via $.myplugin('foo', 'bar')
init : function( options )
{
return this.each(function()
{
// do init stuff
}
},
foo : function() { … },
bar : function() { … }
};
})(jQuery);
Unfortunately, "private" methods (or any property for that matter) can never be called with a "this" prefix in javascript. Anything which is called like this.myFunc(myArgs) must be publicly available.
And "private" methods can only be called from within the scope in which they were defined.
Your original solution is the only one that will work. Yes, it's a pain having to pass in this, but there's no more verbosity than there would be if your impossible request was possible:
this.fill('green');
//or
fill(this,'green');
As you can see, they both take up exactly the same number of characters in your code.
Sorry to say, but you're stuck with this as a solution, unless you want to create a new namespace and make them not private - which is simply going to add to the amount of code you need to write, i.e. what you indirectly called "not directly exposed":
this.myplugin.fill('green');
...is more verbose, thus kind of defeats the purpose.
Javascript is not like other languages, there are no "private" members per-se, only members accessible within closures, which can sometimes be used in a similar way to private members, but is more of a "workaround", and not the "real-deal" private members you are looking for.
It can be difficult to come to terms with this (I often struggle), but don't try to mould javascript into what you understand from other languages, take it for what it is...

Javascript Sandbox unit testing

I am using QUnit, which is excellent.
I have enclosed my JS app in the (function () {})(); sandbox. This hides a lot of code that I don't want public, but I also need to test that code.
Here is an example of how this works:
(function () {
var PublicAPI = window.PublicAPI = {};
PublicAPI.publicFunction = function (foo) {
PrivateAPI.privateFunction(foo);
return 'bar';
};
var PrivateAPI = {};
PrivateAPI.privateFunction: function (foo) {
// Make secret stuff that never gets returned to the public
// Could be an AJAX call.
}
})();
So here I can easily unit test PublicAPI.publicFunction, but how will I test PrivateAPI.privateFunction ?
This similar question sums it up pretty well... The easiest is to not deal with the private methods, as they can change if they want... The public methods are the ones that need testing. If you want to test your internal functions you need to leave a hook of some sort for qunit to be able to find.
You can't. There is no way to access it from outside of that scope. Your only hope is to integration test it, i.e. test functions on the globally available object that are using your internal functions.
Better yet: don't make private functions. What's the big deal?

Categories