350 likes | 612 Views
Singletons. There is no need to produce a class-like constructor for an object that will have exactly one instance.Instead, simply use an object literal.. Singletons. var singleton = { firstMethod: function (a, b) { ... }, secondMethod: function (c) { ... }};. Sing
E N D
1. JavaScript: The Good PartsPart Five: Functional Inheritance
Douglas Crockford
douglas@crockford.com
2. Singletons There is no need to produce a class-like constructor for an object that will have exactly one instance.
Instead, simply use an object literal.
3. Singletons var singleton = {
firstMethod: function (a, b) {
...
},
secondMethod: function (c) {
...
}
};
4. Singletons The methods of a singleton can enjoy access to shared private data and private methods.
5. Functions Functions are used as
Functions
Methods
Constructors
Classes
Modules
6. Closure A function object contains
A function (name, parameters, body)
A reference to the environment in which it was created (context).
This is a very good thing.
7. Module Variables defined in a module are only visible in the module.
Functions have scope.
Variables defined in a function only visible in the function.
Functions can be used a module containers.
8. Global variables are evil Functions within an application can clobber each other.
Cooperating applications can clobber each other.
Use of the global namespace must be minimized.
9. Singletons var singleton = (function () {
var privateVariable;
function privateFunction(x) {
...privateVariable...
}
return {
firstMethod: function (a, b) {
...privateVariable...
},
secondMethod: function (c) {
...privateFunction()...
}
};
}());
10. A Module Pattern var singleton = (function () {
var privateVariable;
function privateFunction(x) {
...privateVariable...
}
return {
firstMethod: function (a, b) {
...privateVariable...
},
secondMethod: function (c) {
...privateFunction()...
}
};
}());
11. Applications are Singletons MYAPP.MyApplication = (function () {
var privateVariable;
function privateFunction(x) {
...privateVariable...
}
return {
firstMethod: function (a, b) {
...privateVariable...
},
secondMethod: function (c) {
...privateFunction()...
}
};
}());
12. Privileged Method A Privileged Method is a function that has access to secret information.
A Privileged Method has access to private variables and private methods.
A Privileged Method obtains its secret information through closure.
13. Module pattern is easily transformed into a powerful constructor pattern.
14. Power Constructors Make an object.
Object literal
new
Object.create
call another power constructor
15. Power Constructors Make an object.
Object literal, new, Object.create, call another power constructor
Define some variables and functions.
These become private members.
16. Power Constructors Make an object.
Object literal, new, Object.create, call another power constructor
Define some variables and functions.
These become private members.
Augment the object with privileged methods.
17. Power Constructors Make an object.
Object literal, new, Object.create, call another power constructor
Define some variables and functions.
These become private members.
Augment the object with privileged methods.
Return the object.
18. Step One function myPowerConstructor(x) {
var that = otherMaker(x);
}
19. Step Two function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
}
20. Step Three function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
that.priv = function () {
... secret x that ...
};
}
21. Step Four function myPowerConstructor(x) {
var that = otherMaker(x);
var secret = f(x);
that.priv = function () {
... secret x that ...
};
return that;
}
22. Power Constructor Public methods (from the prototype)
var that = Object.create(my_base);
Private variables (var)
Private methods (inner functions)
Privileged methods (that...)
No need to use new
myObject = power_constructor();
23. Functional Inheritance A power constructor calls another constructor, takes the result, augments it, and returns it as though it did all the work.
24. function symbol(s, p) {
return {
id: s,
lbp: p,
value: s
};
}
function delim(s) {
return symbol(s, 0);
} function stmt(s, f) {
var x = delim(s);
x.identifier = true;
x.reserved = true;
x.fud = f;
return x;
}
function blockstmt(s, f) {
var x = stmt(s, f);
x.block = true;
return x;
}
25. Pseudoclassical Inheritance
26. Functional Inheritance function gizmo(id) {
return {
id: id,
toString: function () {
return "gizmo " + this.id;
}
};
}
function hoozit(id) {
var that = gizmo(id);
that.test = function (testid) {
return testid === this.id;
};
return that;
}
27. Secrets function gizmo(id) {
return {
toString: function () {
return "gizmo " + id;
}
};
}
function hoozit(id) {
var that = gizmo(id);
that.test = function (testid) {
return testid === id;
};
return that;
}
28. Shared Secrets function gizmo(id, secret) {
secret = secret || {};
secret.id = id;
return {
toString: function () {
return "gizmo " + secret.id;
};
};
}
function hoozit(id) {
var secret = {}; /*final*/
var that = gizmo(id, secret);
that.test = function (testid) {
return testid === secret.id;
};
return that;
}
29. Super Methods function hoozit(id) {
var secret = {};
var that = gizmo(id, secret);
var super_toString = that.toString;
that.test = function (testid) {
return testid === secret.id;
};
that.toString = function () {
return super_toString.apply(that);
};
return that;
}
30. Inheritance Patterns Prototypal Inheritance works really well with public methods.
Functional Inheritance works really well with privileged and private and public methods.
Pseudoclassical Inheritance for elderly programmers who are old and set in their ways.
31. Multiples When assigning functions in a loop, be aware that all of the functions are bound to the same closure.
This can be avoided by using a factor function to produce unique bindings.
32. Warning When creating functions in a loop, do not let the function directly use any variables that are mutated by the loop.
Use closure to protect the loop variables.
while (...) {
... function (...) {
x ... y... z
} ...
}
while (...) {
... function (x, y, z) {
return (function (...) {
x ... y... z
};
}(x, y, z)) ...
}
33. Multiples for (i ...) {
var div_id = divs[i].id;
divs[i].onmouseover = function () {
show_element_id(div_id);
};
}
for (i ...) {
var div_id = divs[i].id;
divs[i].onmouseover = (function (id) {
return function () {
show_element_id(id);
};
}(div_id));
}
34. later method The later method causes a method on the object to be invoked in the future.
my_object.later(1000, "erase", true);
arguments.slice(2)
Array.prototype.slice.apply(arguments, [2]);
35. later method if (typeof Object.prototype.later !== 'function') }
Object.prototype.later = function (msec, method) {
var that = this,
args = Array.prototype.slice.apply(arguments, [2]);
if (typeof method === 'string') {
method = that[method];
}
setTimeout(function () {
method.apply(that, args);
}, msec);
return that;
};
}