Patient Guy wrote:
Quote:
So the question is, how can I set up the code so that method 'method2'
remains a method of the constructor and should not be called as a function
in global scope?
A brief answer:
You can't do it in JavaScript because of a specification bug (because
of well-thought engine mechanics, because of bad implementations of
totally right specifications, because of ... - you really choose the
best from the list or fill your own one: do not start yet another
discussions :-)
Because of this ... phenomenon an external (declared in the Global
scope) function is just an external function no fricking matter what,
even if you made it to be a member of a custom object.
(ECMA specs are telling the same in much more details and by using many
savvy words, but the above sentence really contains all info you really
need to get the idea).
A medium-length answer:
External functions know nothing about custom objects they appertain to
and there is no way to educate them by the conventional ways. But:
a) Unless you are using JScript.NET or planning to use your script in
JScript.NET later: you can augment the function object to hold some
extra info. (JScript.NET if compiled or/and run in quick mode doesn't
allow function augmentation and it will break with error).
b) Functions do not know if and what custom objects do they appertain
to, but they can point *sometimes* to the object-caller over
arguments.caller property. Unfortunately there were security issues
with this property and it is not consistent across modern browsers. It
is either removed all together or partially blocked. It also says
"null" most of the time, and most of the time it says it at the time
when you'd like to hear something completely else :-)
By choosing or by combining both ways And by accepting more narrow set
of supported environments you can emulate in external functions (with
an acceptable level of "trust-wordiness"):
1) Static protected method of a singleton:
<script>
function method1() {
// a lot of code
// and finally:
if (method1.owner) {
window.alert(method1.owner.name);
}
}
function myConstructor() {
if (myConstructor.$instance) {
return myConstructor.$instance;
}
else {
myConstructor.$instance = this;
this.name = 'myObject';
this.method1 = method1;
this.method1.owner = this;
}
}
var obj = new myConstructor();
obj.method1();
</script>
2) Static protected method constructor of a class constructor. That was
I guess what you called "in the scope of constructor method"
<script>
function method1() {
window.alert('The Glory and the mISERY of JavaScript...');
}
method1.toString = function() {
if ((arguments.caller)
&&(arguments.caller === myConstructor)) {
return method1;
}
else {
return window.alert('Error');
}
}
function myConstructor() {
this.method1 = method1;
}
var obj = new myConstructor();
obj.method1();
method1();
</script>
You noticed of course that this method is still only "half-protected".
It will refuse to participate in any constructions unless they led by
myConstructor. You may add to the last check
.... ||(myConstructor.isPrototypeOf(arguments.caller))
to allow not only myConstructor but also its derivates, but it gets a
bit shaky.
At the same time it still can be called as a stay-alone function.
Unfortunately this is only as far as JavaScript goes. Up to you to make
sure that any calls would be useless/harmless outside of the class
constructor (or start to cook with function-wrappers to call your
method but it gets too much ugly to discuss - yet technically
possible).
Long answer:
All of the above was about some abstract JavaScript running within the
engine to only purpose to run. It is not true for the absolute majority
of real cases. In real cases you usually run your scripts to accept
user input and to alter graphics context in some way based on this
input. It means that you almost always need to communicate with DOM and
your scripts actually just a bridge between calculations/requests and
user display. By taking MDI-centric approach it is always possible to
represent your model as certain interface elements (form elements,
images, SVG/VML graphics, tables etc.) and certain behaviors you need
to add into it. By using behaviors ("bindings" by Mozilla) you
eliminate all and every problems with incontinence of "this" and lack
of scope modifiers in standard JavaScript. In behaviors your original
code works as an object factory creating a separate instance for each
bound element. This instance is running in its own separate scope
completely independent from the Global scope. The "this" in such
instance and its methods always points to this individual scope (==
current instance scope) and this scope is not accessible from the
Global scope by any means other then public method defined for the
bound element.
All this may lead to an hysteric from a person who learned JavaScript
by the Books of ECMA only :-) But in fact it is very flexible and
convenient. Unfortunately it currently covers FF, IE, NN and Camino
only (currently good enough for me, but may be not good enough for
you).