Gawain said:
Yeah, prototype is clearly ideal, but I unfortunately don't
have that option -- perhaps a more clear example:
function DivAug() {
this.fun = function() {
//do stuff
}
}
The comment "do stuff" may not provide enough clarity as inner functions
(declarations or expressions) have a specific role in javascript in that
their use may forms closures:-
<URL:
http://www.jibbering.com/faq/faq_notes/closures.html >
In this case it is difficult to see any advantage in using an inner
function expression as the outer function does not have any parameters,
local variables or inner function declarations, so the inner function's
'environment' is empty. Because inner functions may form closures it is
necessary for each such function object to be unique. The language's
specification allows function objects to be re-used when it is
impossible to externally observe the difference between a re-used
function object and two instances of a function object. The observable
difference would relate to the function's internal [[Scope]] property,
and your inner functions would have indistinguishable [[Scope]]
properties because their outer function has no parameters, local
variables or inner function declarations. So it would be possible for an
ECMAScript implementation to execute your code and not be creating a new
function object with each execution of the - DivAug - method. However,
experimentation has revealed no evidence of any ECMAScript
implementations that take advantage of this permitted optimisation.
Generally, you would not want to use an inner function at all unless you
were taking advantage of its special status as an inner function, and
the closure formed by its creation/use.
function MyDiv() {
var div = document.createElement('div');
DivAug.call(div);
return div;
}
The idea I had was that rather than create an external
infrastructure which would manage my DOM structure,
I would simply augment the DOM elements so that they would
know what to do with themselves.
Without any specific example it is not practical to say anything about
this idea.
Unfortunately, I can't muck with a DOM element's prototype.
You certainly cannot on most browsers, which is practically the same as
not being able to at all.
If call creates a new copy of the functions methods with
invocation,
Don't blame this on the function's call method, it is true of inner
functions on all outer function calls. And it is a valuable and
exploitable feature of the language.
And you don't need to use the call method here (indeed you almost never
need to use the call method).
I guess I'm going to have to rethink everything from scratch.
Not at all. You just need to augment all the DIV elements created with
references to a single function object. You could define that function
globally:-
function forDivFun(){
//do stuff
}
- and either directly augment the DIVs following creation:-
var div = document.createElement('div');
div.fun = forDivFun;
- or have another function do the augmentation:-
function DivAug(div){
div.fun = forDivFun;
}
You probably will not want to (should not want to) define the functions
that will act as methods of your objects globally, but you have many
methods of creating such method in a 'private' scope. For example, the
inline execution of a function expression:-
var divAug = (function(){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
return (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
});
})();
The inline execution of the function expression only happens once (as
the script loads) so the inner functions - forDivFun - and - forDivBar -
are only created once, but the function returned and assigned to the
global - divAug - variable is able to assign references to those
function object instances to all the DIVs passed to it as arguments (-
divAug(div) -).
The main drawback with the inline execution of a function expression is
that you cannot use the - divAug - function until after the source code
for it has been executed, so the order of the code becomes important
(rarely a significant problem).
An alternative 'private' scope strategy is the "Russian doll" pattern
(named as such because the outer aspect of a function is replaced with
smaller, more specific, inner aspect during its execution):-
fucntion divAug(div){
function forDivFun(){
//do stuff
}
function forDivBar (){
//do more stuff
}
(divAug = (function(div){
div.fun = forDivFun;
div.bar = forDivBar;
}))(div);
div = null;
}
When this function is called for the first time (as - divAug(div); - the
two inner functions - forDivFun - and - forDivBar - are created and then
the global - divAug - function is replaced with an inner function that
has access to - forDivFun - and - forDivBar -. This new function is
called, passing on the div parameter of the outer function so it may be
augmented. Finally the - div - parameter is assigned null so that no DOM
element references are preserved in the closure.
Following the first call to the above function all subsequent calls
transparently execute only the inner function that replaced it. (Thus
the to - forDivFun - and - forDivBar - function objects are only created
once but may be assigned to all DIVs to be augmented).
This strategy means that the set-up/configuration of the divAug function
is delayed until its first use.
Thanks for the (albeit disappointing) info.
By the way, does this not render object augmentation
essentially useless in all but trivial cases?
Augmentation is completely viable, though augmenting 800+ DOM elements
seems a bit extreme. But ore information/context would be needed to
fairly judge the idea.
Richard.