My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label scope. Show all posts
Showing posts with label scope. Show all posts

Thursday, September 09, 2010

JavaScript Protected Properties

Imagine this simple piece of code:

var obj = {
_name: "protected",
gimmeName: function () {
return this._name;
}
};

obj.gimmeName(); // "protected"
obj._name; // throws new Errror

now, imagine I have the simplest solution ever, compatible with both ES5 and ES3 genric implementations ... now please keep reading to know a bit of background :)


The JS Meaning Of Protected

JS developers know that in JavaScript properties are always public and that it is possible to attach/detach properties in any moment to a generic object. Regardless this fact, many libraries consider protected, by naming convention, all those properties whose name start with "_".


You Are Doing It Wrong

First of all I keep saying that is a common error trying to bring classical Object Oriented concepts into a completely different language as JavaScript is, but it does not matter ... we want protected stuff, right?
Due dynamic nature, the common protected meaning is pointless. See this example:

var obj = {
_name: "",
getName: function () {
return this._name;
},
setName: function (_name) {
this._name = _name;
}
};

getName and setName method are theoretically the only one able to change the _name property ... correct? Why, 'cause these are object methods ???

var obj.iCreateAnotherMethod = function (_whateverIWant) {
this._name = _whateverIWant;
};
obj.iCreateAnotherMethod(
"JS protected JOKE"
);

Now try to argue that a dynamic object with a dynamic associated method should not be able to perform the same operation setName does ...


At Least Do It Better!

All protected I have seen so far are quite prolix, inefficient, or pointless.
First of all, let's analyze the problem: what protected should be.
For protected we may consider all those properties or methods that should not be accessed directly but that can be accesses by public (or protected) methods of the same instance.
In few words, we would like to be sure that these properties are not easily accessible outside the object.


An ES5 Friendly Implementation



Object.defineProtectedProperty = (function (
defineProperty // from Object
) {
// (C) WebReflection - Mit Style License

// check that a caller is an object method
function check(object, caller) {
// this function accesses enumerable
// properties.
// returns instantly if check()
// was the property accessor
// (avoid recursion)
if (caller === check) {
return;
}
// avoid direct calls
// in the global scope
// ( or via apply/call )
if (caller) {
for (var key in object) {
if (
// the caller is a method
// ( property wrapper )
object[key] === caller
) {
return;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}

// named expression (we like debugging)
return function defineProtectedProperty(
object, // the generic object
key, // the generic key
description // the ES5 style description
) {
// cache the value
var value = description.value;
// remove it since get/set + value
// does not make sense
delete description.value;
// define the getter
description.get = function get() {
check(object, get.caller);
return value;
};
// define the setter
description.set = function set($value) {
check(object, set.caller);
value = $value;
};
// define and return
return defineProperty(object, key, description);
};
}(Object.defineProperty));

Here some usage example:

// generic object
var o = {
greetings: function () {
this._sayHello();
}
};

// protected property
Object.defineProtectedProperty(
o, "_hello",
{value: "Hello World"}
);

// protected method
Object.defineProtectedProperty(
o, "_sayHello",
{enumerable: true, value: function () {
alert(this._hello);
}}
);

// method call
try {
o._sayHello();
} catch(e) {
alert(e); // access denied
}

// property access
try {
o._hello = "no way";
} catch(e) {
alert(e); // access denied
}

o.greetings(); // Hello World

The only thing to remember is that by default, enumerable is false so, if we would like to access a protected property inside a protected method, we must set it as enumerable so the for/in loop can discover it and verify it as object method.
Pros: compatible with all latest browsers, included IE9, with the only exception of WebKit and Safari (but I have already filed a bug there). It is possible to specify all defineProperty description, in this case except get and set.

Cons: not compatible with less recent browsers plus the check may cost if protected properties are constantly accessed. Address these properties once if it's needed to use them multiple time. Set them once as well if it's needed to change their value.


An ES3 Friendly Implementation

Here the version compatible with many other browsers, witohut the possibility to set ES5 properties such enumerable, configurable, and writable. It is also not possible to avoid a delete operation, which could cause problems.

Object.defineProtectedProperty = (function () {

// (C) WebReflection - Mit Style License

// check that a caller is an object method
function check(object, caller) {
// this function accesses enumerable
// properties.
// returns instantly if check()
// was the property accessor
// (avoid recursion)
if (caller === check) {
return;
}
// avoid direct calls
// in the global scope
if (caller) {
for (var key in object) {
if (
// the caller is a method
// ( property wrapper )
object[key] === caller
) {
return;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}
return function defineProtectedProperty(
object, // the generic object
key, // the generic key
value // the generic description
// only value is considered
) {
value = value.value;
// define the getter
object.__defineGetter__(key, function get() {
check(object, get.caller);
return value;
});
// define the setter
object.__defineSetter__(key, function set($value) {
check(object, set.caller);
value = $value;
});
// return the object
return object;
};
}());

The same usage showed in the precedent example so that migration to ES5 version will be less painful.

Pros: compatible with almost all current browsers except IE family and WebKit/Safari due same bug reported before.

Cons: less secure than ES5 version since delete operation is allowed and properties then re-configurable. Other cons from ES5 version.


The caller Is Dead, Long Life to the Caller

In ES5 they keep removing powerful stuff considering all developers idiots unable to understand JS ... at least this is my feeling when I read things like "the with statement is dangerous" and "with 'use strict' caller should throw an error".
I don't really mind if they remove arguments.callee, we can always use function expressions (IE < 9 a part), but the genericFunction.caller is one of the most fundamental properties every function could possible have.
As instance, it wouldn't be even possible to think about my protected proposal without the caller, while internally all engines know who is the first level outer scope since they need it for variables resolution (e.g. when an inner scope uses an outer scope variable). Is this truly a performances issue? I don't think so, but I have not yet tested it so ... let's see ...


A Scoped Alternative For Every Browser

The only real private thing in JavaScript is a function scope, where this is private only from its outer scope, unless we don't hack it bringing there stuff via eval:

function toOuterScope($) {

var x = 1;

return eval($);
}

alert(toOuterScope("++x")); // 2
alert(typeof x); // undefined

Accordingly, the best way ever to ensure some sort of protection is to store properties into a private scope.
This is the alternative that works with every browser:

var scoped = (function () {

// (C) WebReflection - Mit Style License

// the only real private thing in JS
// is a function scope, like this one
// variables here are private/scoped as well
var
stack = [], // objects collection
id = [], // objects ids
n = -1, // object not found
// minifier shortcuts
indexOf = "indexOf",
push = "push",
splice = "splice"
;

// speed up the get(self, key)
// if indexOf returns -1 we don't care
// we return something from Object.prototype
stack[n] = {};

// ensure that outside nobody can change
// id or stack used Array.prototype methods
// (assignment rather than inherited chain)
id[push] = id[push];
id[splice] = (stack[splice] = id[splice]);
// for Jurassic browser implement a quick indexOf
id[indexOf] = id[indexOf] || function (value) {
for (var i = id.length; i--;) {
if (id[i] === value) {
break;
}
}
return i;
};

// unregister the object
// and all scoped properties
function clear(self) {
var i = id[indexOf](self);
if (n < i) {
id[splice](i, 1);
stack[splice](i, 1);
}
}

// retrieve the scoped property value
function get(self, key) {
// no shortcut to avoid lookup
// slightly better performances
return stack[id.indexOf(self)][key];
}

// set the scoped property value
function set(self, key, value) {
var i = id[indexOf](self);
if (n == i) {
stack[i = id[push](self) - 1] = {};
}
stack[i][key] = value;
}

// named function (we like debugging, don't we?)
function scoped(key, value) {
var
// verify who called the scoped function
caller = scoped.caller,
// improve minifier ratio
self = this,
// one var is enough, undefined is safer
property, undefined
;
// avoid direct calls
// e.g. obj.scoped()
// in a global context
if (caller) {
// loop them all
for (property in self) {
// check if object's method is the caller
if (self[property] === caller) {
// undefined or null key means clear(self)
return key == null ? clear(self) :
// value === undefined means get(self, key)
// otherwise means set(self, key, value)
value === undefined ?
get(self, key) :
set(self, key, value)
;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}

// ready to go
return scoped;

}());

Above variable can be used as object property (method) or as prototype method without problems, and here we have some usage example:

// generic constructor
function F() {}

// scoped as prototype
F.prototype._scoped = scoped;
// getter
F.prototype.getProtected = function (key) {
return this._scoped(key);
};
// setter
F.prototype.setProtected = function (key, value) {
this._scoped(key, value);
};
// clear all scoped properties
F.prototype.clearProtected = function () {
this._scoped();
};

// generic instance
var f = new F;

// set protected
f.setProtected("test", 123);
alert(f.getProtected("test")); // 123

// re-set
f.setProtected("test", 456);
alert(f.getProtected("test")); // 456

// clear all
f.clearProtected();

alert(f.getProtected("test")); // undefined

// try to access scoped
try {
f._scoped();
//scoped.call(f, "whatever");
} catch(e) {
alert(e); // access denied
}

Less Magic With Methods

If we would like to reproduce initial code example, we should tweak the object in a weird way, e.g.


var o = {
_scoped: scoped,
init: function () {
var self = this;
self._scoped("_hello", "Hello World");
self._scoped("_sayHello", function _sayHello() {
self._sayHello = _sayHello;
alert(self._scoped("_hello"));
delete self._sayHello;
});
},
greetings: function () {
this._scoped("_sayHello")();
}
};

// call the init to set scoped properties
o.init();

try {
o._scoped("_sayHello")();
} catch(e) {
alert(e); // access denied
}

try {
o._scoped("_hello", "no way");
} catch(e) {
alert(e); // access denied
}

o.greetings(); // Hello World

This latest alternative is indeed ideal for properties but not methods.
Pros: compatible with basically every browser. No enumeration at all, detached properties.
Cons: not intuitive as other options. Properties must be set via init. We need to clear properties when we don't need the object anymore. Performances are not better than other options.


As Summary

Protected properties are closer here but still we should remember the runtime method that should logically be able to set a protected property ... this is JavaScript, not Java or C#, so probably we should be stuck with the idea that protected and private, in latter case scope talking a part, do not make sense and whatever we do can only decrease overall performances, too often granting a slightly better security.

Tuesday, October 13, 2009

Internet Explorer Scope Resolution

I have enclosed in only 5 steps JScript weirdness, hoping all precedent deliriums about functions, standards, and Internet Explorer, will make more sense now.

Here there is the link to original HTML slides, I hope this will help everybody to have clearer ideas.

Saturday, October 10, 2009

Named function expressions demystified

Update If after this reading things are still the same, please read the part 2 of this post, thanks.



This is a re-post, and few considerations, about the good Juriy article, which I suggest for every JavaScript developer with a deeper knowledge than just an API (jQuery or others).

Github For Everything!

My first consideration is about github, something I've never used that much since via Google Code I feel pretty comfortable with subversion. I find truly interesting the way Juriy is tracking his documentation, I've never thought about an article, as my old JavaScript Prototypal Inheritance could be, in a code repository as kangax did: good stuff!

My Alternative Solution

There are few extra consideration to do over Juriy explanation, plus minor inconsistencies. The first thing is that Internet Explorer basically manages Function expressions and Function declarations in the same way, there's no such VS in the middle.
The fact we assign the function to a whatever named variable does not make any difference:

alert(F); // (function F(f){/*IE Function*/return f})

F((function F(f){/*Function Declaration*/return f}));
F((function F(f){/*IE Function*/return f}));

var f = (function F(){return F}); // <== which F?
function F(){/*IE Function*/}; // this one!

alert(f()); // function F(){/*IE Function*/};
We can play with above IE traps for ages but the point is simple: the last defined function with that name, will simply take the place of the other one, if any, in the same scope, and at the end of its resolution, before code execution.

What IE does is basically a top-down parsing over functions without taking care at all about code execution or normal and expected syntax execution flow.
This simply means that return whatever, var whatever = function whatever(){} ... does not change anything for our loved IE:what we see or what we expect is not what will be, otherwise IE would have been a perfect browser.
To better understand what I am talking about, this example should speak for me:

var f = 123;
alert(F); // last function
(function(){
alert(F); // (function F(){alert(f);return arguments.callee})
var f = (function F(){alert(f);return arguments.callee})();
// undefined
})();
function F(){};

After these two snippets is quite logical understand this behavior:
  1. scope resultion
  2. function resolution plus optional inline assignment, if any, before next function resolution
  3. code interpretation/execution over scope resolution

Accordingly with this Richard Cornford post, in JScript every function is performed sending the execution context, a behavior somehow similar to the injected context via eval in Firefox few months ago.
The latter one has been considered a security hole ... same kind of hole we need to deal with IE on daily basis every time we would simply chose a name for a bloody function.

My Solution

Juriy perfectly knows my point of view about this problem, he knows it so well that his addEvent solution example is created ad hoc to make mine inefficient (and I'll tell you later why).
It does not matter, as long as I can use the same example, avoiding IE4 support ...

var addEvent = (function(){
var docEl = document.documentElement;
if (docEl.addEventListener) {
/* return */ function addEvent(element, eventName, callback) {
element.addEventListener(eventName, callback, false);
};
} else {
// IE has to be the last option
// other addEvent will be "lost"
// cause this will be the only named reference
// in this scope ...
function addEvent(element, eventName, callback) {
element.attachEvent('on' + eventName, callback);
}
};
return addEvent;
})();

The key is simple, and is based exactly over same considerations and suggestions Juriy gives in the Alternative solution paragraph, except my suggestion uses an explicit last option callback, without requiring var this or that plus var this or that = null in any place, and for this purpose.

Indeed, for the same reason Juriy did not perform this task at the end of his latest suggestion and before the returned function:

if (typeof docEl.addEventListener != 'undefined') {
attachEvent = addEventAsProperty = null;
return addEventListener;
}
elseif (typeof docEl.attachEvent != 'undefined') {
addEventListener = addEventAsProperty = null;
return attachEvent;
}
addEventListener = attachEvent = null;
return addEventAsProperty;


totally boring and absolutely anti pattern, on daily basis and real case scenarios, with my suggestion there is absolutely no need to remember to nullify variables used only to refer inline assignments and, moreover, only as Internet Explorer workaround!!! That's too much, I mean we have to change our code, change JS logic, to support such drama JS engine, we even need to write more and nullify everything? No way!

But It Could Be Inefficient

The only real side effect about my suggestion, surprisingly working in Safari 2 as well and solving its problems with names, is that if we have to deal with two different versions of IE in the same scope, we cannot use the "last definition" trick, 'cause one out of 2, 3, or 234567 versions of the most problematic browser since Web epoc, still Internet Explorer and JavaScript speaking, will mess up like a charm ... to be honest, IE4 days, the one without try catch and much more support, are far away from 2009, and I've never had to deal with such problem but in this case, there is nothing better, so far, than Juriy proposal.

Update
In my addEvent example Opera, thanks to its duality, will behave IE like. This is not a problem, since addEvent will work in any case, but we can return if we would like to force Opera with addEventListener (avoiding Safari 2 then). To solve this problem, when necessarym we can use the best from both proposal.

Re Solution


var addEvent = (function(){
var docEl = document.documentElement,
addEvent;
if (docEl.addEventListener) {
addEvent = function addEvent(element, eventName, callback) {
element.addEventListener(eventName, callback, false);
}
}
else {
addEvent = function addEvent(element, eventName, callback) {
element.attachEvent('on' + eventName, callback);
}
}
return addEvent;
})();
Quite semantic, isn't it? ;)
The principle is still the same suggested by Juriy except there is nothing to nullify, just a reference to return, and being based on variable assignment, we can have 2345IE versions in the if else without problems at all.

As Summary

In Internet Explorer there is no difference between function expression and function declaration, this is the whole point of this post, plus the updated suggestion which makes things a bit more logical, from a developer point of view - addEvent is a well defined reference, and that's what we need.
The var F = null; in Juriy suggestion is useless for IE. References comes after, in the interpretation flow, while references come before in the execution one. var F = null; will nullify a reference, it won't mark anything for the IE garbage collector.
Juriy article is in any case a must read as soon as we understand JavaScript scope and lambdas, and specially if we would like to support multiple browsers.
Hopefully these gotchas will disappear with ES5 and the next "dreamed" IE9 with its totally new fabulous V8 engine ( OK, OK, ... let me dream please ... )
The day IE will disappear from browsers panorama I'll be the most happy and drunk web developer in the area but until that day, we can say the panorama is still weird, at least well explained, and with all possible solutions, we have choices!

Wednesday, October 22, 2008

a new Relator object plus unshared private variables

This is a Robert Nyman's post dedicated reply, about JavaScript inheritance and alternatives and private variables.

First of all, I would like to say thanks to Robert for both interesting articles He is writing about JS inheritance, and a link to a personal comment which aim was to bring there my "old" documentation about classical JavaScript inheritance and usage of prototype, closures, and public, privileged, or private, scope when we create a constructor.

About


Last Rob's post talk about private variables, describing them as shared, if present outside the constructor, and valid only for singleton instances.
This is true, and could cause a lot of headache if we are not truly understanding closures and prototype shared methods behaviour, but there is a way to use this peculiarity about shared private variables to create dedicated private variables.

Before I will write about it, let's look into a generic shared private variable example:

Click = function(){
// closure for private methods / variables

// private shared variable
var _total = 0;

// returned constructor + prototype
function Click(){};
Click.prototype.add = function(){
_total++;
};
Click.prototype.getTotal = function(){
return _total;
};
return Click
}();

var left = new Click,
right = new Click;

left.add();
alert(right.getTotal()); // 1

Above example shows that if a variable is created outside the constructor and prototype shared methods use that variable, every call to one of those method from a generic instance will modify that single private variable, created once inside that closure. To obtain a private variable we need privileged methods:

Click = function(){ // privileged methods
var _total = 0;
this.add = function(){
_total++;
};
this.getTotal = function(){
return _total;
};
};

var left = new Click,
right = new Click;

left.add();
alert(right.getTotal()); // 0

As discussed before in my doc, in robert's posts, and everywhere else in the web, privileged methods create many functions for each instance, and with big projects this is not good for both memory and CPU usage.

new Relator object and unshared private variables


The Relator is an object capable to relate a generic variable with a clear object, without modifying the original variable.
The classic example is this:

var myNum = 123;
Relator.set(myNum).description = "I am number 123";
alert(myNum.description); // undefined
alert(Relator.get(myNum).description); // "I am number 123"

Since with Relator it is possible to create a unique relation between a generic object and a private Object, it was natural for me to think that a private variable could be a Relator like object using this as unique relationship.
The new version of my Relator still respect the precedent API, being a Relator itself, but is now able to return a new object Relator like that could be used, as example, inside a closure.

// new Relator can create a Relator like object with method "$"
PrivateRelator = function(Relator){
// Relator argument is a new Relator like object
// present only in this scope
return {
get:function(what){
var value = Relator.get(what);
return value && value.value;
},
set:function(what, value){
Relator.set(what).value = value;
}
}
}(Relator.$()); // create a new Relator

Relator.set(window).value = "Hello World";
Relator.get(window).value; // Hello world
PrivateRelator.get(window); // undefined
PrivateRelator.set(window, "Hello Private World");
PrivateRelator.get(window); // Hello Private World
Relator.get(window).value; // Hello World

The good part of Relator is that the stored variable, if it is an object, is stored by reference, and we can assign more than a private unique relationship between a single object and our extra informations.
The same pattern could be easily re-adapted to create a shared private variables:

Person = function(){

// private methods
function _getName(){
return _private.get(this).name
};
function _setName(name){
_private.get(this).name = name;
};

// private variable, shared by every function in this scope
var _private = Relator.$();

// constructor + prototype
function Person(){
// bridge to _private shared variable
_private.set(this);
};
Person.prototype.getName = function(){
return _getName.call(this);
};
Person.prototype.setName = function(name){
_setName.call(this, name);
};
return Person;

}();

// extended constructor
function Enhanced(){
// necessary to save
// this instance into _private variable
// accessible only via Person scope
Person.call(this);
};
(function(){ // quick runtime extend
var callee = arguments.callee;
if(this instanceof callee)return;
callee.prototype = Person.prototype;
Enhanced.prototype = new callee;
})();


var me = new Person(),
rob = new Enhanced();

me.setName("Andrea");
rob.setName("Robert");

alert([me.getName(), rob.getName()]);
// Andrea,Robert


Conclusion


Sometime a limitation could be easily managed to obtain desired result.
In this case, thanks to JavaScript closures and its prototype nature, the shared variable become a sort of bridge to obtain private variables for each instance.
It is important to understand that even if we extend the base constructor, every new instance will still persist into original _private variable, inside the Person scope, unless we do not specify a different one, redefining every method that use that variable as well:

(function(_private){
Enhanced = function(){
_private.set(this);
};
(function(){ // quick runtime extend
var callee = arguments.callee;
if(this instanceof callee)return;
callee.prototype = Person.prototype;
Enhanced.prototype = new callee;
})();
Enhanced.prototype.getName = function(){
return _private.get(this).name
};
Enhanced.prototype.setName = function(name){
_private.get(this).name = name;
};
})(Relator.$());


See you soon ;)

Tuesday, April 08, 2008

Famous documentation and the dark side of "this" !

The good thing of internet is that you can find a lot of free documentation.
At the same time, the bad thing of internet, is that this documentation is rarely updated.

It could be a "guru documentation" or it could be a newbie documentation, but in both cases, it doesn't matter because it is probably wrong, not updated, or too generic.

This post has not enough space to describe every error you can find on, and off line ... so let me start with some true example about a common misunderstood referer, the this one.

Douglas Crockford and Private Members in JavaScript


This page is famous enough, and I suppose that every true JavaScript developer has read them at least once.
The main error in that page is described in this sentence

By convention, we make a private that parameter. This is used to make the object available to the private methods. This is a workaround for an error in the ECMAScript Language Specification which causes this to be set incorrectly for inner functions.

We know, or maybe we don't, that everything without a prefix will be executed in the global scope or in nested closure, if any. But even if a function is created inside a method, it fortunately does not make sense to call a function that has not been assigned as instance method and find a this reference inside.

// guys, this function ...
window.testMe = function(){};

// is exactly the same of this one
function testMe(){};

// or this one in a global scope
var testMe = function(){};

The main reason we do not need to use window when we call a global method, or function, is that everything in JavaScript is virtually executed like in a global window with statement (that's why write window.open is redundant and nothing else ... and Stargate code is totally redundant too :D).

// this code ...
window.onload = function(){};

// is exactly the same of this one
onload = function(){};

onload();

// that is virtually similar to ...
with(window){
onload();
};

Let's focus on the onload example in the middle ... ok? Who will be the this referer if we do not use call or apply Function.prototype methods? window, of course.
And as window has a self property, that a link to window itself, if we use alert(this === self); it will be true every time we will use onload();
If we assign onload function as object method

onload = function(){
alert(this === self);
alert(this === window);
};
var o = {};
o.onload = onload;

... we will read two alerts with two false instead of two true value.
This simply means that to use a function that has not been assigned as method, or better, that is not called from a method, the this reference will be the global object.

onload = function(){
alert(this === window);
};
onload(); // true
var o = {onload:onload};
o.onload(); // false

function useCallback(callback){
callback();
};

useCallback(o.onload); // false again

I do not really know why Doug defined this an error in ECMA Specification, but if it really is, what could be the logic behaviour, an "unpredictable" default this referer even if the nested function is not inside an instance constructor?
I don't think so.

The intrinsic constructor Factory Design Pattern


Thanks to this "error", we could use a constructor in two ways or recognize when it has been called with new or as function.
If it is an error, it couldn't be possible to know this kind of useful information.

function Person(name, age){

// this is true only if we used
// new before Person constructor
if(this instanceof Person){
this.name = name;
this.age = age;
} else

// otherwise we used the constructor
// as factory design pattern (in this example)
return new Person(name, age);
};

// these two lines do the same thing: create a Person instance
var me = Person("Andrea", 29), // doyou like python style, don't you?
you = new Person("You", null);

alert(me instanceof Person); // true
alert(you instanceof Person); // true

Anyway, as I wrote in my recent and updated documentation, that passed totally unobserved, we do not need a that variable for nested private function.

function Person(name, age){
function setNameAndAge(){
this.name = name;
this.age = age;
};
// to call setNameAndAge as private
// method we do not need a that
// but only call or apply Function.prototype
// methods to inject instance as this referer
setNameAndAge.call(this);
};
alert(
(new Person("Andrea", 29)).name // Andrea
);

Finally, I have to admit that Douglas Crockford is my favourite JavaScript professor, and it's basically thanks to him that I know what I know about JavaScript. He wrote a lot of interesting JS stuff, and some document is truly updated, explaining for example errors wrote in old one.

My programming style has evolved since then, as any good programmer's should. I have learned to fully embrace prototypalism, and have liberated myself from the confines of the classical model.

Every programmer should evolve because in this sector knowledge is never enough. So thanks a lot Doug, but please update your 2001 doc writing something more about this, that, scope, injected this, and closures :D (a link to this post should be appreciated as well)

Ross and Dustin in Pro JavaScript Design Patterns


Differently, here we are in late 2007 ... December 2007
For some reason, few days ago someone posted again this book in Digg ... and for the first time, I read about them.

It seems to be really a good book, but without reading them, I've just downloaded examples trying to imagine what are these used for.

Fortunately, and thanks to Apress or authors decision, these sources are free and well organized inside chapter folders, each file with dedicated paragraph.

Well done ... but at the third chapter, I've read a pseudo "horror" in file 3.07 ...

var Class = (function() {

// Constants (created as private static attributes).
var UPPER_BOUND = 100;

// Privileged static method.

// ... that will never work, where is the function?
this.getUPPER_BOUND() {
return UPPER_BOUND;
}
// Return the constructor.
return function(constructorArgument) {
//
}
})();

Forgetting the missed = function, that could be a common error during quick development, getUPPER_BOUND is a privileged method of the global scope, aka window, and it is not static, it is like a window.getUPER_BOUND call, where this is obviously the window itself.
As I wrote few lines before, if we use this inside a function it will refer to window object. That's why after we can see a wrong example like this one:

var Class = (function() {
var constants = {
UPPER_BOUND: 100,
LOWER_BOUND: -100
}
// again ...
this.getConstant = function(name) {
return constants[name];
}
return function(constructorArgument) {
//...
}
})();

// anyway ... Error!!!
Class.getConstant('UPPER_BOUND');

alert(Class.getConstant); // undefined
alert(getConstant); // expected function


I am pretty sure that if this code is the one showed to explain privileged, that chapter could be full of errors ... please update them putting correct code and free corrected page inside the zip ... otherwise, sorry for this correction.

Finally, Dustin and Ross are two JavaScript ninjas, and reading the rest of the code it seems that I absolutely need to find that book because I do like design patterns and I am so curious to know how are their implementation (good stuff guys!).

Conclusion


I am the first one that writes horrible code, and probably I've even forgot what I wrote one year ago and where ... so the only suggestion I could write is that if you find something interesting, or something that you did not know, look for something else and look every time for the date that document has been published.

Have fun with self instruction, and never stop ;)