473,289 Members | 2,087 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,289 software developers and data experts.

Getting name of object instance from within object method

I'd like to be able to get the name of an object instance from within
a call to a method of that same object. Is this at all possible?

The example below works by passing in the name of the object instance
(in this case 'myDog'). Of course it would be better if I could
somehow know from within write() that the name of the object instance
was 'myDog' without having to pass it as a parameter.

////////////////////////////////
function Dog(name)
{
this.name = name;
this.write = function(objID)
{
document.write(
'<a href="javascript:void(', objID,
'.bark())">Your dog\'s name is ', this.name, '</a>'
);
}

this.bark = function()
{
alert('"Woof", said '+this.name);
}
}

var myDog = new Dog('Rex');
myDog.write('myDog');
////////////////////////////////

This example creates an instance of an object and draws it to the
screen in the form of a clickable link. When clicked this link calls
the bark() method on the object.
Jul 23 '05 #1
6 22472
Martin wrote:
I'd like to be able to get the name of an object instance from within
a call to a method of that same object. Is this at all possible?


Of course. But you mean the identifier instead, and I doubt that retrieving
that is possible, at least not cross-browser. The reason is that your
"myDog" is _not_ the object, it is but a reference to it and what you call
the "name" is in fact the identifier of an object reference. I may create
another reference to the same object, say

var yourDog = myDog;

and then call

yourDog.write(...);

What is the "name" of the calling object?
PointedEars
--
I sync, therefore I am.
Jul 23 '05 #2
Martin wrote:
I'd like to be able to get the name of an object instance
from within a call to a method of that same object.
Is this at all possible?
If you mean the name of a variable (probably global) that refers to an
object instance then no you cannot. Many variables (global or otherwise)
may refer to the same object instance and there is no mechanism by which
an object can know which variables refer to it (let alone to make a
choice among the potentially many variables that might refer to it).
The example below works by passing in the name of the
object instance (in this case 'myDog'). Of course it
would be better if I could somehow know from within
write() that the name of the object instance
was 'myDog' without having to pass it as a parameter.
That is a completely normal requirement and numerous techniques are
available for achieving it. Different techniques suit different
contexts: In the context of assigning event-handling function to DOM
elements by reference a closure based approach is relatively simple:-

<URL: http://jibbering.com/faq/faq_notes/closures.html#clObjI >

The context of wanting to use - document.write - or the - Function -
constructor is better addressed by having the object instance assign a
global reference to itself that it knows how to address independently of
how other code might be using references to it. This is probably
simplest done by creating an array as a named property of the
constructor and having each object instance assign a reference to itself
as an element in that array, keeping track of the index that it used for
the assignment:-

function myObject(){
this.index = myObject.instances.length;
myObject.instances[this.index] = this; //reference to this object
//instance assigned to the
//(public static) array;
...
}
myObject.prototype.write = fucntion(){
document.write('<a href="#" onclick="return myObject.instances['+
this.index+
'].method();">...<\/a>');
}
myObject.prototype.method = fucntion(){
...
return false;
}
myObject.instances = []; // This is analogous with creating a 'public
// static' array of object instances. Being
// a property of the constructor allows the
// array to be globally accessible.

////////////////////////////////
function Dog(name)
{
this.name = name;
this.write = function(objID)
Assigning an inner function of the constructor at this point creates a
closure. You are not exploiting this closure (it has no advantages when
you are trying to refer to object instance through code written as
text), and so it would be more efficient to defined the object's -
write - method on the constructor's prototype (so only on instance of
the corresponding function object is created).
{
document.write(
'<a href="javascript:void(', objID,
Do not ever use a javascirpt: pseudo protocol HREF, they play havoc with
web browsers. (Use - onclick - handlers that return true or false
depending on whether the navigation specified in the HREF is to be
followed (false - in this context). Or use <input type="buttion">
elements to perform non-navigation javascript dependent actions.)
'.bark())">Your dog\'s name is ', this.name, '</a>'
);
}

this.bark = function()
{
alert('"Woof", said '+this.name);
}
}

var myDog = new Dog('Rex');
myDog.write('myDog');
////////////////////////////////

This example creates an instance of an object and draws it
to the screen in the form of a clickable link. When clicked
this link calls the bark() method on the object.


The javascript object cannot know that you have used the variable named
"myDog" to refer to the object instance unless you pass it the string
"myDog", but you don't necessarily have to do that as explained above.

Richard.
Jul 23 '05 #3


Martin wrote:
I'd like to be able to get the name of an object instance from within
a call to a method of that same object. Is this at all possible?

The example below works by passing in the name of the object instance
(in this case 'myDog'). Of course it would be better if I could
somehow know from within write() that the name of the object instance
was 'myDog' without having to pass it as a parameter.

////////////////////////////////
function Dog(name)
{
this.name = name;
this.write = function(objID)
{
document.write(
'<a href="javascript:void(', objID,
'.bark())">Your dog\'s name is ', this.name, '</a>'
);
}

this.bark = function()
{
alert('"Woof", said '+this.name);
}
}

var myDog = new Dog('Rex');
myDog.write('myDog');


But what is the "name of the object instance" if someone codes
var myDog1, myDog2;
myDog1 = myDog2 = new Dog('Rex');
? There is nothing like the "name of an object instance", you can have
several variables and/or object properties refer to the same object.
--

Martin Honnen
http://JavaScript.FAQTs.com/
Jul 23 '05 #4
Thank you for your responses.

Of course I realise now that my request to get the variable name was a
little strange. This is because I really wanted to somehow get a
reference to the calling object. As Richard pointed out, this is
possible with closures. I have only just discovered closures - they
don't seem to be discussed in any Javascript books I have read.

Although I haven't used the method of creating an array of object
instances I have modified my example:
function Dog(name)
{
this.name = name;
}

Dog.prototype.write = function()
{
var txtEl = document.createElement('A');
txtEl.href = '#';
txtEl.innerHTML = 'Your dog\'s name is '+this.name;
txtEl.onclick = Dog.callDoOnClick(this);

document.body.appendChild(txtEl);
}

Dog.callDoOnClick = function(obj){
return function(ev){
obj.bark(ev);
};
};

Dog.prototype.bark = function(ev)
{
alert('"Arf", said '+this.name);
}
This works as I expect, although I'm not quite sure why
callDoOnClick() is not created in the object prototype, and what the
implications of doing so would be.

Another question I have relates to Douglas Crockford's 'privileged'
member functions. In the example above, what are the consequences of
creating the write() and bark() functions inside the constructor (and
hence privileged) versus creating them in the prototype (and hence
public)? Other than affecting the scope of the variables they can
access, is it simply a memory conservation technique?
Jul 23 '05 #5
On 20 Aug 2004 02:32:15 -0700, Martin <dj*********@gmx.net> wrote:

[snip]

I'm not sure how coherant my explanation will be, so I apologise if I
confuse you. Richard's usually the one explaining this sort of thing. :)

I think I'll take your questions in a different order than you ask them. I
think it will be easier to understand the other issues once you fully
understand privaledged methods (which you seem to have doubts about).
Another question I have relates to Douglas Crockford's 'privileged'
member functions. In the example above, what are the consequences of
creating the write() and bark() functions inside the constructor (and
hence privileged) versus creating them in the prototype (and hence
public)? Other than affecting the scope of the variables they can
access, is it simply a memory conservation technique?
If you know other OO languages, like Java and C++, you'll be familar with
the different access types: public, protected, and private. Each of these
is provided as a basic part of the language. Javascript doesn't provide
these labels, but it does allow the concept through the use of closures.

Javascript only has two types of scope: variables as object properties,
and function scope[1]. As you can't mark object properties as private or
protected, there's only one way to prevent access to a member: make it
local.

function myObject() { // Constructor
var myMember; // Private member
}

Now myMember can only be accessed from within the object. However
traditional approaches to adding methods won't work here.

function myObject() {
var myMember;
}
myObject.prototype.myMethod = function() {
return myMember; // ERROR!
};

To do it, we need a closure.

function myObject() {
var myMember;

this.myMethod = function() {
return myMember; // OK
};
}

The method, myMethod, is "privaledged" because it's public, but can access
private data, unlike other public methods (like the first one).

The reason that Richard objected to your use of closures in the first
version of your code is because you didn't take advantage of their
behaviour. If myMember was added to the prototype (either with
this.myMember or prototype.myMember), you could access it from either of
the two methods above simply using

return this.myMember;

To use the feature properly, you code should have looked something like:

function Dog(name) {
this.bark = function() {
alert('"Arf!", said ' + name);
};
// Likewise with write()
}

Here, you still access the name that was given to the dog upon
instantiation, but without revealing the data to the world to see and
possibly alter.

You don't have to worry about losing data with this approach; on each
instantiation of Dog, name will refer to separate data and each
privaledged method will use the correct one.

So to summarise the answers to your last two questions:

1) Privaledged members can access data that was declared local inside the
class. Members added via the prototype cannot.
2) Privaledged members allow the application of proper OO design.

So far, I've only described private members. Richard once showed me how to
implement protected members. Whilst the concept works, it takes a lot of
effort, and a lot of code. It's rarely that useful, though I have used it
once. If you're interested, you could search for it in the Google archives.

[snipped code]
This works as I expect, although I'm not quite sure why callDoOnClick()
is not created in the object prototype, and what the implications of
doing so would be.


What you've created there is a static method: it exists on the constructor
only has no means of accessing instance or private data. It can't access
instance data because it doesn't have the this operator set to any
particular instance (it's set to the constructor). It can't access private
data as it doesn't form a closure within the constructor.

Adding it to the prototype instead would mean that you'd have to call the
method from an instance, rather than the constructor, and you still
couldn't access private data, the this operator would be set to the object
you called the method from.

Once part of the prototype, you could then change the method to:

Dog.prototype.callDoOnClick = function() {
var o = this;
return function(e) {
o.bark(e);
};
};

which takes advantage of privaledged members concept.

I hope that helps, but remember: this is my first attempt at an
explanation.

Mike
[1] Some might argue that there's also global scope, but this is just an
instance of the first type: global variables are properties of the global
object.

--
Michael Winter
Replace ".invalid" with ".uk" to reply by e-mail.
Jul 23 '05 #6
Martin wrote:
Of course I realise now that my request to get the variable
name was a little strange. This is because I really wanted
to somehow get a reference to the calling object. As
Richard pointed out, this is possible with closures. I have
only just discovered closures - they don't seem to be
discussed in any Javascript books I have read.
One of the reasons for the generally lamentable state of javascript
authoring for the Internet is that the vast majority of the books
available on the subject are actively bad. Out of date, teaching bad
techniques and often containing misinformation. They are rarely written
by javascript experts, which isn't surprising as being good a browser
scripting is no qualification for writing books on the (or any) subject.
The Internet is worse because there is nothing to stop anyone from
publishing anything they like and promoting it as instructional.

I am told that David Flanagan's: javascript: The Definitive Guide (4th
Edition ISBN:0-596-00048-0) does cover closures. That is one of the
reasons that it is considered the best javascript book currently
available. But even then, though I have not seen the full 4th edition
myself, the sample chapters of that book available through the O'Reilly
press web site do include some examples of techniques that I would
consider dubious (and only use to illustrate what not to do), such as -
navigator - object based browser detection. so even the best book
available is not an ideal guide to learning browser scripting.

Closures do seem to be a largely overlooked aspect of javascript. In
practice they were introduced at about JavaScript 1.2 along with inner
functions, so initially they probably seemed too risky for Internet use.
When I first became aware of, and interested in, javascript closures,
there was almost no information available on the subject through google
searching, beyond the general computer science theoretical explanations
in on-line encyclopaedias.

These days they have been fully formalised in ECMA 262 (3rd edition)
since 1999, so they should be available in all current javascript
implementations. However, there remains a tendency to take the "java" at
the beginning or javascript a little too literally and apply a Java
mindset to thinking and writing about javascript, and Java has no
closures (inner classes being as close as it gets), so the Java mindset
has no idea about what to do with them.

There has been a recent outbreak of wider interest in closures, with
closure-based techniques appearing in the blogs of some well-known
script authors, and a knock-on interest in related blogs. It is actually
quite entertaining to read of people 'discovering' closure based
techniques which have been in frequent use on this group for at least a
couple of years.

The page I posted the URL of yesterday:-

<URL: http://jibbering.com/faq/faq_notes/closures.html >

- is my explanation of javascript closures. It attempts to explain the
underlying mechanism in terms of the structures of objects (function
objects and scope chains) specified in ECMA 262 and facilitating lexical
scopeing in javascript implementations. It is the most complete
description of javascript closures that I have seen to date (and was
peer-reviewed on this group for technical accuracy prior to
publication).
Although I haven't used the method of creating an array
of object instances I have modified my example:
When you are not using - document.write -, or the - Function -
constructor the array of instances (which could have been an object with
uniquely named properties instead) is no longer the best approach.
Closures are better (given proper handling).

function Dog(name)
{
this.name = name;
}

Dog.prototype.write = function()
{
var txtEl = document.createElement('A');
txtEl.href = '#';
txtEl.innerHTML = 'Your dog\'s name is '+this.name;
Using innerHTML at this point is a little inconsitent. As you are only
adding text creating and inserting a new text Node with -
document.createTextNode - would sit better with the use of the other W3C
DOM Core methods. The strength on innnerHTML comes when the content to
be inserted is HTML mark-up, and is too complex (or unknown) to easily
code using DOM methods.
txtEl.onclick = Dog.callDoOnClick(this);

document.body.appendChild(txtEl);
}

Dog.callDoOnClick = function(obj){
return function(ev){
obj.bark(ev);
};
};

Dog.prototype.bark = function(ev)
{
alert('"Arf", said '+this.name);
}

This works as I expect, although I'm not quite sure why
callDoOnClick() is not created in the object prototype,
and what the implications of doing so would be.
It isn't created on the prototype because you have created it as a named
property of the constructor and that has no impact on the
constructor's - prototype-e - object. The only practical implication of
creating the function on the constructor's prototype instead is that you
could call - callDoOnClick - as a method of the object instance and use
the - this - keyword to refer to the instance, e.g.:-

Dog.prototype.callDoOnClick = function(){
var obj = this;
return (function(ev){
obj.bark(ev);
});
};

I don't see any advantage in doing it that way. Conceptually the -
callDoOnClick - function is not a method of the object instance, it is a
'class utility', and as such probably belongs in a position that is
analogous with "static" in class-based languages. It is a class utility
because it offers the same functionality to any and all instances of the
'class' but is of no use to other classes as it explicitly uses the
"bark" method of the object instance. The example in closures.html takes
the object instance and the method name as parameters so it is a more
general utility function (that can be used by any 'class', and for more
method calls per-instance).

In terms of efficiency there would also be little difference between the
two, as in each case only one - callDoOnClick - function object is
created (and the function is probably not going to be called often
enough for any difference between resolving - this.callDoOnClick - and -
Dog.callDoOnClick - to be significant (the second should be fractionally
slower as it requires a search down the scope chain to the global object
in order to resolve - Dog -, while - this - is known immediately in any
execution context)).
Another question I have relates to Douglas Crockford's
'privileged' member functions. In the example above, what
are the consequences of creating the write() and bark()
functions inside the constructor (and hence privileged)
versus creating them in the prototype (and hence public)?
Other than affecting the scope of the variables they can
access, is it simply a memory conservation technique?


There is provision in ECMA 262 for function object 'sharing', where two
functions that are externally indistinguishable are allowed to be
optimised into two references to the same function object instance.
Inner functions used in closures are unlikely to be externally
indistinguishable (because they will have distinct internal [[scope]]
properties), and there is evidence that existing ECMAScript
implementations do not feature this optimisation anyway.

As a result, whenever execution enters a function body that contains an
inner function definition (or a function expression is evaluated) a new
function object is created as that inner function. With a method defined
on the prototype there is only one function object corresponding with
each method, and all instances inherit a reference to that one function
object through their internal [[prototype]] property.

This means that assigning inner functions of the constructor to public
members of an object instance will result in a different function object
existing in the system for each such method of each object instance.
More function objects will consume more memory, and creating distinct
function object with each invocation of the constructor will slow down
object instantiation.

Thus I would recommend only using 'privileged' methods when they are
needed (when the closure produced has a valuable and specific purpose).
Otherwise the prototype is the place to be creating public methods (this
is only general advice as other approaches, such as 'object
augmentation', can be as efficient as prototype inheritance and more
flexible). It is important to understand when and *why* you are creating
closures, particularly because accidental closures often end up
containing otherwise inaccessible references to DOM objects which might
provoke the memory leak problem on IE browsers (as discussed at the end
of closures.html).

Richard.
Jul 23 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: marktm | last post by:
Hi- I am trying to use setInterval to call a method within an object and have not had any luck. I get "Object doesn't support this property or method" when I execute the following code. What I...
2
by: Wouter de Kort | last post by:
I've started looking at Aspect Oriented Programming but I've stumbled at a problem I can't solve. I want to add an Aspect that would notify a UnitOfWork that the current DomainObject has changed...
9
by: Dennis | last post by:
When a class (myownclass) inheirits another class, how can I get an object reference to the underlyng MyBase class instance from within myownclass. The base class has a method that I want to...
11
by: Alexander Walker | last post by:
Hello I would like to write a method that allows me to pass a reference to an instance of a class, the name of a property of that class and a value to set that property to, the method would then...
20
by: Shawnk | last post by:
I would like to get the class INSTANCE name (not type name) of an 'object'. I can get the object (l_obj_ref.GetType()) and then get the (l_obj_typ.Name) for the class name. I there any way of...
7
by: RSH | last post by:
This is probably a very simple question but... How do I get the instantiated name of an object from within the class? Example: Sub main Dim c1 as new TestClass() c1.PrintName()
5
by: reycri | last post by:
Hi, I need to be able to do this: var func = new Function("var me = <selfRef>; alert(me.params);"); func.params = "This is a test parameter"; window.setTimeout(func, 500); Basically, I...
2
by: karinmorena | last post by:
I'm having 4 errors, I'm very new at this and I would appreciate your input. The error I get is: Week5MortgageGUI.java:151:cannot find symbol symbol: method allInterest(double,double,double)...
0
by: TG | last post by:
Hi! Once again I have hit a brick wall here. I have a combobox in which the user types the server name and then clicks on button 'CONNECT' to populate the next combobox which contains all the...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.