473,382 Members | 1,386 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,382 software developers and data experts.

Namespaces, or getting function foo.bar() declarations to work

Hi!

I don't think I've ever been here, so I assume I'm addressing a bunch of
nice people. Can you help me? I don't think there's a solution, but who
knows.

The thing is, picture a large project where you want some encapsulation.
But a lot of it being grouping of what would otherwise be static members
of the global namespace. So that instead of

fooEcks(), fooWye, fooZed()

you can have

foo.ecks(), foo.wye(), foo.zed()

with foo being a global variable.
Now this is perfectly possible, that I know, by declaring

var foo={} OR function foo(){}

and then having

foo.ecks=function(args){body}

or then by defining them inline, as in

var foo={ecks: function(args){body}}

However, in all of these, the functions created are anonymous. This may
make no difference, but I don't like it and it impacts debugging, when
you're trying to determine their name.

You can given them a name, as in

foo.ecks=function ecks(args){body}

But this is error prone, since you have to keep the two names in sync,
and that is a sure road to damnation.
It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then your
foo.ecks function. I may be missing something, but this seems great to
me, in absence of alternatives (my preferred would be simply that
internal named functions were public).

But as it is, neither Opera nor Gecko accept this notation. And for the
life of me, I haven't been able to figure out any other way to define a
public static member (though instance members would have the same
problem) that isn't anonymous without referring its name twice. Needless
to say, something like

var foo={ecks: fooEcks};
function fooEcks(args){body};

isn't the solution because it keeps the repetition (though this time it
could be automated to avoid errors - but notice that then we're going
far away from the natural constructs of the language), clutters the
global namespace anyhow, and probably creates all sorts of scope
problems (otherwise, we may just delete all of those references after
reassigning the functions to their namespace, but somehow this doesn't
look like a sensible solution).

So, any ideas? Thanks,
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #1
14 1613
António Marques wrote:
<snip>
However, in all of these, the functions created are anonymous.
This may make no difference, but I don't like it and it impacts
debugging, when you're trying to determine their name.

<snip>

This assumption appears to be the crux of your issue, but you have not
explained or justified it. Most javascript error reports output line
numbers (at minimum) so I don't see any need to have a name associated
with the function for debugging.

Richard.
May 25 '06 #2
Richard Cornford wrote:
However, in all of these, the functions created are anonymous.
This may make no difference, but I don't like it and it impacts
debugging, when you're trying to determine their name.


This assumption appears to be the crux of your issue, but you have not
explained or justified it. Most javascript error reports output line
numbers (at minimum) so I don't see any need to have a name associated
with the function for debugging.


It's not an assumption, they really are anonymous. But you are right
that it it the crux of the issue: both that I can't extract a name for
them, and more generally that they don't have one. If I could get a name
I'd be happy, even if the function were anonymous the same. In fact, I
wouldn't mind at all, since for instance I'd like internal functions to
yield the name of their context and not their own:

function foo()
{
function bar()
{
debug('hello', 1, 'a')
}
}

And function debug would output something like

'10:04:55 [foo] hello, 1, a'

As to the why, javascript error reports are more or less the equivalent
of exception stack traces. They can be informative, and a script
debugger may help hunt down and fix an error, but debug outputs have
their own value.

Maybe there's something hidden in the function object that I haven't
discovered yet.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #3
António Marques wrote:
Hi!

I don't think I've ever been here, so I assume I'm addressing a bunch of
nice people. Can you help me? I don't think there's a solution, but who
knows.

The thing is, picture a large project where you want some encapsulation.
But a lot of it being grouping of what would otherwise be static members
of the global namespace. So that instead of
[...]
However, in all of these, the functions created are anonymous. This may
make no difference, but I don't like it and it impacts debugging, when
you're trying to determine their name.

You can given them a name, as in

foo.ecks=function ecks(args){body}

But this is error prone, since you have to keep the two names in sync,
and that is a sure road to damnation.
This question is asked from time to time, you can try searching the
archives for answers but you've already summarised the case. Try this
thread:

<URL:http://groups.google.co.uk/group/comp.lang.javascript/browse_frm/thread/800641e55d59fb3a/bfab46faf88c7443?q=arguments.callee&rnum=3#bfab46f af88c7443>

The real question is 'why do you want to know'? Presumably for
debugging, where you could use arguments.callee to get the name of the
function. The "best" solution is the one you've already discounted:

foo.ecks = function ecks(...){...};

Another 'solution' is to pass the function name to the function when you
call it.

It is highly desirable that stuff specific to debugging can be easily
removed for production code - implementing either of the above will make
that very difficult.

It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then your
foo.ecks function. I may be missing something, but this seems great to
me, in absence of alternatives (my preferred would be simply that
internal named functions were public).
Do you mean:

function foo(){
function bar(){}
}
bar(); // Error: bar is not defined.

What would be the point of declaring a function inside a function object
(i.e. creating a 'private member') if it was then public?

But as it is, neither Opera nor Gecko accept this notation. And for the
life of me, I haven't been able to figure out any other way to define a
public static member (though instance members would have the same
problem) that isn't anonymous without referring its name twice. Needless
to say, something like

var foo={ecks: fooEcks};
function fooEcks(args){body};


Read this post by Richard Cornford regarding class concepts (public,
private, etc.):

<URL:http://groups.google.co.uk/group/comp.lang.javascript/browse_frm/thread/d6460f64f2222442/952287418c33ae6c?q=arguments.callee&rnum=7#9522874 18c33ae6c>

It may seem a little obtuse in regard to your question, but it's a good
read anyway.
--
Rob
Group FAQ: <URL:http://www.jibbering.com/faq/>
May 25 '06 #4

António Marques wrote:

The thing is, picture a large project where you want some encapsulation.
But a lot of it being grouping of what would otherwise be static members
of the global namespace. So that instead of

fooEcks(), fooWye, fooZed()
What is your objection to this method?

you can have

foo.ecks(), foo.wye(), foo.zed()
Richard explained to me just yesterday that this is a bad idea because
JavaScript is not compiled but rather interpreted. He wrote

"Simulated namespaces are a very questionable notion. In other language
the namespaces are resolved when the code is compiled. Javascript must
resolve those long property accessors each and every time they are
used."

You can find the whole post in the archives of this newsgroup.

However, in all of these, the functions created are anonymous. This may
make no difference, but I don't like it
maybe sometimes it is worth going with the flow of the language
and it impacts debugging, when
you're trying to determine their name.


Firefox spits out line numbers which makes it no problem.

Peter

May 25 '06 #5
António Marques <m.**@sapo.pt> writes:
You can given them a name, as in

foo.ecks=function ecks(args){body}

But this is error prone, since you have to keep the two names in sync,
and that is a sure road to damnation.
Then only write it once:
---
// extract name from function's toString
function funcName(func) {
var match = /^\s*function\s+([\w$]+)[^\w$]/.exec(func.toString());
if (match) {
return match[1];
}
}

// extend object with named methods
function addMethods(target /*, functions...*/) {
for(var i = 1; i < arguments.length; i++) {
var func = arguments[i];
if(typeof func == "function") {
var name = funcName(func);
if (name) {
target[name] = func;
}
}
}
return target;
}

// test
var ns = addMethods({accumulator:[]},
function add(n) {
this.accumulator.push(n);
return this;
},
function sum() {
for(var i=0,r=0; i < this.accumulator.length; i++) {
r+=this.accumulator[i];
}
return r;
});

alert(ns.add(2).add(40).sum()); // alerts 42
---
It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then
your foo.ecks function.


Nice idea, especially for extending prototypes:
function Foo.prototype.doFoo() { ... }
instead of
Foo.prototype.doFoo = function doFoo() {...}

But it's completely non-standard, so only viable for scripting
specific known browsers and not for internet use.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
May 25 '06 #6
António Marques wrote:
Richard Cornford wrote:
However, in all of these, the functions created are
anonymous. This may make no difference, but I don't
like it and it impacts debugging, when you're trying
to determine their name.
This assumption appears to be the crux of your issue, but
you have not explained or justified it. Most javascript
error reports output line numbers (at minimum) so I don't
see any need to have a name associated with the function
for debugging.


It's not an assumption, they really are anonymous. ...

<snip>

That was not the assumption. The assumption was that using anonymous
functions would impact debugging. It is an assumption as anonymous
functions are common on non-trivial javascript and if their use really
was a problem when debugging that would have been noticed by now.
function foo()
{
function bar()
{
debug('hello', 1, 'a')
}
}

And function debug would output something like

'10:04:55 [foo] hello, 1, a'

<snip>

The 'hello' got into that output because you put it there, why not put
in the information that tells you what you need in the output, like
something that tells you the context of the debug call?

Richrd.
May 25 '06 #7
RobG wrote:
(stuff)
Thank you for the references, Rob.
Some things are just hard to find out other than asking them to a
knowledgeable group (it's easy enough to find the answer to 'how to do
X?', but not necessarily so when the question amounts to 'in how many
ways can X be done?'), and you seem knowledgeable alright (this language
is so generally misunderstood that one must be careful).
It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then
your foo.ecks function. I may be missing something, but this seems
great to me, in absence of alternatives (my preferred would be simply
that internal named functions were public).


Do you mean:

function foo(){
function bar(){}
}
bar(); // Error: bar is not defined.


( Actually foo.bar() )
What would be the point of declaring a function inside a function object
(i.e. creating a 'private member') if it was then public?


I'd like it to be public. To define a private function, one could use a
private variable and assign a function to it.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #8
pe**********@gmail.com wrote:
The thing is, picture a large project where you want some
encapsulation. But a lot of it being grouping of what would
otherwise be static members of the global namespace. So that
instead of

fooEcks(), fooWye, fooZed()


What is your objection to this method?


And:
you can have

foo.ecks(), foo.wye(), foo.zed()


Richard explained to me just yesterday that this is a bad idea
because JavaScript is not compiled but rather interpreted (...)


Thanks for the pointer - I'll follow this on the other thread.
and it impacts debugging, when you're trying to determine their
name.


Firefox spits out line numbers which makes it no problem.


But debugging in particular and logging in general is so much more than
looking at exception reports.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #9
Lasse Reichstein Nielsen wrote:
You can given them a name, as in

foo.ecks=function ecks(args){body}

But this is error prone, since you have to keep the two names in sync,
and that is a sure road to damnation.


Then only write it once:
(...)
// extend object with named methods
function addMethods(target /*, functions...*/) {
for(var i = 1; i < arguments.length; i++) {
var func = arguments[i];
if(typeof func == "function") {
var name = funcName(func);
if (name) {
target[name] = func;
}
}
}
return target;
}

// test
var ns = addMethods({accumulator:[]},
function add(n) {
this.accumulator.push(n);
return this;
},
function sum() {
for(var i=0,r=0; i < this.accumulator.length; i++) {
r+=this.accumulator[i];
}
return r;
});


Hey, this looks great! But will the final code behave just in the same
way as if it were defined with

var ns = {accumulator:[]};
ns.add = function add(n) { ... };
ns.sum = function add(n) { ... };

?
I see it does in the test given, but I ask this because of the scope
chain - it seems to me that the first scope in both cases is the owner
of var ns, but is it really?
It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then
your foo.ecks function.


Nice idea, especially for extending prototypes:
function Foo.prototype.doFoo() { ... }
instead of
Foo.prototype.doFoo = function doFoo() {...}

But it's completely non-standard, so only viable for scripting
specific known browsers and not for internet use.


I was very unhappy when I found out it was IE specific.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #10
Richard Cornford wrote:
However, in all of these, the functions created are
anonymous. This may make no difference, but I don't
like it and it impacts debugging, when you're trying
to determine their name.

This assumption appears to be the crux of your issue, but
you have not explained or justified it. Most javascript
error reports output line numbers (at minimum) so I don't
see any need to have a name associated with the function
for debugging.


It's not an assumption, they really are anonymous. ...


That was not the assumption. The assumption was that using anonymous
functions would impact debugging. It is an assumption as anonymous
functions are common on non-trivial javascript and if their use really
was a problem when debugging that would have been noticed by now.


I said why it impacts debugging, if no one else is bothered by that is
another matter. For all I know, people are tearing their hair off for
the short supply of great javascript IDEs. I don't think it would hurt
that a name could be determined for every function (if not their own,
that of the variable they are assigned to, or that of the scope object).
function foo()
{
function bar()
{
debug('hello', 1, 'a')
}
}

And function debug would output something like

'10:04:55 [foo] hello, 1, a'


The 'hello' got into that output because you put it there, why not put
in the information that tells you what you need in the output, like
something that tells you the context of the debug call?


Only because it would have to be done every time. Given the dynamic
nature of javascript, it's even possible that 'bar' is bound to other
scope, so maybe something like

'10:04:55 [foo > bar] hello, 1, a'
'10:04:57 [dif > bar] hello, 1, a'

would be even more interesting. The next version of ECMAScript could
surely define some more meta- functionality for functions, something
that could be put to good use by IDEs.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 25 '06 #11
António Marques <m.**@sapo.pt> writes:
Hey, this looks great! But will the final code behave just in the same
way as if it were defined with

var ns = {accumulator:[]};
ns.add = function add(n) { ... };
ns.sum = function add(n) { ... };


It should, yes. There are no other scopes involved.

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
May 25 '06 #12
António Marques wrote:
RobG wrote:
It turns out that in IE6, if you do

function foo(){}; // with 'var foo' it won't work
This line should work with `var foo' as well, but the next line should
not work anyway.
function foo.ecks(args){body};

the browser does create a member of foo, named ecks, which is then
your foo.ecks function.
It works only in IE6 this way because it uses a proprietary extension of
ECMAScript (or an implementation flaw). The FunctionDeclaration production
requires the `function' keyword to be followed by whitespace, followed by
an _identifier_ (not by a property accessor in dot notation), followed by
the parameter list followed by the function body. Therefore, the standards
compliant way is

function foo() {}

or a FunctionExpression, where the identifier after the `function' keyword
is optional:

var foo = function() {};

And then:

foo.ecks = function(args){ /* body */ };

Because `foo' is always a reference to a Function object that can be
augmented, like any native object:

var foo = {}; // or `= new Object()'
foo.ecks = function(args){ /* body */ };

or

var foo = {
ecks: function(args){ /* body */ };
};
I may be missing something, but this seems great to me,
Even if written standards compliant, it has its drawbacks. One is that
you need another function object. Another one, that I have pointed out
recently, is that if you use the Function object as a constructor,
objects created with it will not inherit the ecks() method; you have to
augment the constructors prototype object to achieve that.
in absence of
alternatives (my preferred would be simply that internal named functions
were public).


Do you mean:

function foo(){
function bar(){}
}
bar(); // Error: bar is not defined.


( Actually foo.bar() )


foo.bar() in this context works only in JavaScript 1.5 due to a proprietary
extension of ECMAScript (or an implementation flaw). With the advent of
Gecko 1.8b2+ based UAs, like Firefox 1.5, that use JavaScript 1.6, it has
become not only a deprecated practice but also an obsolete one.
PointedEars

P.S.
Please don't remove attribution lines for quoted text that related to them.
--
A man who works with his hands is a laborer; a man who works with his
hands and his brain is a craftsman; but a man who works with his hands
and his brain and his heart is an artist.
-- Louis Nizer, lawyer (1902-1994)
May 26 '06 #13
pe**********@gmail.com wrote:
António Marques wrote:
you can have

foo.ecks(), foo.wye(), foo.zed()
Richard explained to me just yesterday that this is a bad idea because
JavaScript is not compiled but rather interpreted.


Probably you misunderstood, since JavaScript is (JIT-)compiled, then
interpreted. Compiled vs. interpreted language is not the issue, but
the moment of evaluation of identifiers is:
He wrote

"Simulated namespaces are a very questionable notion. In other language
the namespaces are resolved when the code is compiled. Javascript must
resolve those long property accessors each and every time they are
used."

PointedEars
--
This is Usenet. It is a discussion group, not a helpdesk. You post
something, we discuss it. If you have a question and that happens to get
answered in the course of the discussion, then great. If not, you can
have a full refund of your membership fees. -- Mark Parnell in alt.html
May 26 '06 #14
Hi,

Thank you all for your help on this matter.
--
am

laurus : rhodophyta : brezoneg : smalltalk : stargate
May 29 '06 #15

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

Similar topics

18
by: Steven Bethard | last post by:
In the "empty classes as c structs?" thread, we've been talking in some detail about my proposed "generic objects" PEP. Based on a number of suggestions, I'm thinking more and more that instead of...
15
by: Stuart | last post by:
I work in a small company with developers who do not like to use "new" features when they find the old ones sufficient. e.g. given a choice between a class and a namespace, they'll pick class. ...
17
by: clintonG | last post by:
Using 2.0 with Master Pages and a GlobalBaseClass for the content pages. I understand the easy part -- the hierarchical structure of a namespace naming convention -- but the 2.0 IDE does not...
36
by: Wilfredo Sánchez Vega | last post by:
I'm having some issues around namespace handling with XML: >>> document = xml.dom.minidom.Document() >>> element = document.createElementNS("DAV:", "href") >>> document.appendChild(element)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.