MozillaZine

Javascript Coding Guideline

Discuss building things with or for the Mozilla Platform.
Torisugari
 
Posts: 1634
Joined: November 4th, 2002, 8:34 pm
Location: Kyoto, Nippon (GMT +9)

Post Posted September 17th, 2004, 8:29 pm

These days, I think we need more explicit rules for coding scripts in order to enable to read/understand/reuse each others', and to prevent our products from conflicting.

Chapter 1. Naming Convensions

There's 6 basic rules.
  1. Every variable object name's 1st char should be a lower case.
    Code: Select all
    var myName = "Torisugari";
  2. Every constant object name should be upper cases.
    Code: Select all
    const MY_NAME = "Torisugari";
  3. Every constructor name's 1st char should be an upper case.
    Code: Select all
    function Mozillazine(){
      this.description="A Cool Site";
      this.name="mozillaZine";
      this.url="http://www.mozillazine.org/";
    }
    var gMyFav = new Mozillazine();
  4. By prefix g the author means that is a global object, and unique in the window.
  5. By prefix a the author means that is an argument.
  6. By prefix _ the author means that is a private member.
Bad Examples, though gramatically correct.
Code: Select all
var bar=0; /*bar should be gBar*/
function foo(){
  var gFoobar = 0; /* gFoobar is not a global value */
  return gFoobar;
}


Code: Select all
function foo(bar){  /* bar should be aBar */
  var aFoobar="foo" + bar; /* aFoobar is not an argument */
  return aFoobar;
}


Code: Select all
var gFoo={
  _bar:0
}

var foobar=gFoo._bar; /* _bar is a public member ? */
/* In other words, you can write only "this._bar" */


exceptions
A global function doesn't have to start with g.

My extensions are not good yet, so I'll correct them step by step.
Anybody, more rules, exceptions, comments?

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted September 17th, 2004, 9:00 pm

In order to prevent conflicts, global vars/functions in overlays (especially those in scripts for browser.xul) need to be prefixed with an unique string. gFoo is used by everyone, gAsqueellaFoo is not likely to be used by anyone but me.

BTW, posting here won't get it readed by too many extension developers.

gorgias
 
Posts: 226
Joined: March 19th, 2003, 4:03 pm
Location: Sweden

Post Posted September 19th, 2004, 12:31 am

I think these guidelines are good, I will try to follow them in the future ;) but as asqueella says they don't solve the problem with conflicts

In my extensions I try to use the form:

Code: Select all
var myextension =
{
  someVar: 3,

  init: function()
  {
     doSomething();
  }
};

I got it from Ben Goodgers' extension template and I think this is a good way to namespace everything. If some global variabels are needed why not just name them myextensionSomeName or gMyextensionSomeName if preferred and if some extensions conflicts anyway it shouldn't be too difficult to find the source. What I think is really missing is some good place to read about these issues. Just one webpage, easy to find, that explains how these things works would be enough.

A little off topic...
One thing I haven't managed to figure out is how to use the "this" keyword properly. Given the code above, if I want to change the value of someVar from inside myextension I believe I should be able to write this.someVar = 5; This seems to work most of the time but not always and I can't understand why. If someone could explain this to me I would appreciate it very much.

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted September 19th, 2004, 11:20 am

re: offtopic.
I don't know, but the feeling I've got is: you get this problem when passing someObject.function as parameter to another function like setTimeout or addEventListener, because of either a bug or something that I believe is called "execution context" (I don't know the exact definition of that). The point is: when you pass a function in such way, you don't pass its parent object with it.

Mook
 
Posts: 1752
Joined: November 7th, 2002, 9:35 pm

Post Posted September 19th, 2004, 11:27 pm

Yeah, my rules of thumb are:
  • If called as object.function() then <code>this</code> is the object
  • If called on an event handler, <code>this</code> is the element that triggered the event
  • If called via a reference to the function (in my case, passed it to XPCOM), <code>this</code> is the function itself

All of this, of course, is evaluated when the function is executed, so if you call it differently then the same variable in the function resolves to different kinds of things...

As for code organization, I'm going overboard and using window.extensions.author.extension; this way, I can be pretty sure that I won't ever overwrite something internal to the app (since I prefix it with .extensions), nor ever collide with somebody else (since .author takes care of that... Unless somebody else decides to call themselves Mook). I use either gorgias' method (I copied it from SmartSearch, IIRC) or just set methods on the variable (<code>window.extensions.mook.foo.method = function() { ... }</code>) if I need to load parts of the object from separate files. (In case one of them loads before the other; both sides do a check from the top level downwards to be sure all parent objects exist.) If I needed to make classes, I'd probably do the same except use the .prototype bit.

Also, for element ids (inserted via XUL overlays), I do the same (minus the window. prefix), complete with the dots. It works and hopefully is equally collision resistant. Incompatibities with other extensions seems to mostly be from them overriding the functionality of the app for now :)

Of course, I don't have that many extensions written yet, so all of this isn't without a lot of experience; just that unrelated stuff I've done before have taught me to program really defensively.
poot.

rue
 
Posts: 673
Joined: June 10th, 2003, 2:20 pm

Post Posted September 26th, 2004, 4:29 pm

Pt.i
It's very easy to tell people "this is how you should do it". The difficulty is answering 'why?'. So I'll point, instead, at some resources which directly altered my understanding of JavaScript and how to build a coding-style around it. <blockquote> <ul><li>what <a href="http://www.crockford.com/javascript/index.html">Douglas Crockford</a> found</li><li>the proper, <a href="http://groups-beta.google.com/group/netscape.public.mozilla.jseng/browse_thread/thread/8232d738a011d968/d4b29ce17dafdc06">forward-compatible method</a> for getters/setters</li><li>the whole <a href="http://lxr.mozilla.org/mozilla/source/js/src/jsinterp.c">js-interpretor</a></li><li><a href="http://homepage.mac.com/rue/JS_Optimization_Techniques">speed-optimized</a> JavaScript</li><li>Scope, closure and other <a href="http://jibbering.com/faq/faq_notes/closures.html">tricky concepts</a></li> </ul></blockquote> --
Pt.ii
Torisugari wrote:...
4. By prefix g the author means that is a global object, and unique in the window.
5. By prefix a the author means that is an argument.
6. By prefix _ the author means that is a private member.

Actually, I have a strong preference against those points. I prefer visually dense, clearly-named code. To my eyes "aBar" is not a word, and takes longer to cognitively process than simply "bar", or even "arg1".
.
When working with other people's code (including Torisugari's :P), one of the first things I do is rewrite all variables / function-names to undo that.

[ i. updated links -rue ]
Last edited by rue on February 9th, 2005, 3:53 am, edited 1 time in total.

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted September 28th, 2004, 12:06 pm

rue, do you know if "var bar = { get foo() {} }" is ok?

as for "bar vs. aBar", IMO the worst thing is when author uses mixed style.

I copied info to the kb, and I'm hoping to update that basing on discussion here. Edit whatever you think needs to be edited.

Torisugari, is chapter 2 coming? Perhaps if you published the whole TOC (;-) ), I'd have more ideas.

rue
 
Posts: 673
Joined: June 10th, 2003, 2:20 pm

Post Posted September 29th, 2004, 1:09 pm

asqueella: <a href="http://lxr.mozilla.org/mozilla/source/xpcom/sample/nsSample.js#18">Looks good</a>.
.
Btw, check this out: <a href="http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&c2coff=1&safe=off&frame=right&th=2ee40e5c3a0bd7e8&seekm=3C398C15.8090401%40freenet.de#link4">sharp variables</a>.

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted October 5th, 2004, 11:36 am

On the topic of standartization:
What's about including scripts in XUL files? I've seen a lot of different methods:
Code: Select all
<script type="application/x-javascript" src="chrome://package/content/script.js"/> <!-- most of Mozilla source -->
<script type="application/x-javascript" src="script.js"/> <!-- Adblock -->
<script src="chrome://package/content/script.js"/> <!-- Chatzilla, SessionSaver-->
<script src="script.js"/> <!-- Adblock, Chatzilla -->


Are they equivalent? If not, what are the differences (I can only think of a reason to include type attribute)? In common case, which one should be used and why?

Looks like the "right" way is to include both type and src attributes. I'd use the shortest one if they all mean (and will always mean) the same.

rue
 
Posts: 673
Joined: June 10th, 2003, 2:20 pm

Post Posted October 5th, 2004, 11:59 am

Following various discussions + comments, JavaScript was granted special treatment across-the-board -- including being the "default expected type" when none is specified.
.
For path-access, relative urls have worked consistently since moz1.0. The inconsistencies in Adblock and SessionSaver reflect updated knowledge, on my part. Your last variant is what I prefer, now.

asqueella
 
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post Posted October 7th, 2004, 8:09 am

rue, thanks for your explanation, very much.

I have yet another question, what does "m" prefix mean. It's used quite a lot in Mozilla source, but in few extensions (and where it is used, it has the meaning of "a" or something like that).

rue
 
Posts: 673
Joined: June 10th, 2003, 2:20 pm

Post Posted October 7th, 2004, 12:48 pm

My observation is that m-variables are mutably used as convenience-pointers, and shouldn't be relied-on outside their original use -- they could disappear at any time.
.
I have similar reservations about g, but with less cause.

TheOneKEA

User avatar
 
Posts: 4864
Joined: October 16th, 2003, 5:47 am
Location: Somewhere in London, riding the Underground

Post Posted October 7th, 2004, 1:17 pm

Does anybody write their JavaScript using the Linux kernel CodingStyle document? I do, and all this discussion is making me nervous...
Proud user of teh Fox of Fire
Registered Linux User #289618

Torisugari
 
Posts: 1634
Joined: November 4th, 2002, 8:34 pm
Location: Kyoto, Nippon (GMT +9)

Post Posted October 8th, 2004, 2:41 am

TheOneKEA wrote:Does anybody write their JavaScript using the Linux kernel CodingStyle document?

Why linux kernel? It has nothing to do with javascript nor netscape. Take a look at Mozilla Coding Sytle Guideline.


I don't think everyone have to be compliant with this guideline. However, you'll have hard time when reading the moz source, if you don't know these rules at all.
http://lxr.mozilla.org/aviarybranch/search?string=gstr
http://lxr.mozilla.org/aviarybranch/search?string=aval
http://lxr.mozilla.org/aviarybranch/sea ... ing=this._

btw, overlay is another problem. rue, adblock has simple named overlay onto browser.xul, e.g. "console"...?
asqueella wrote:In order to prevent conflicts, global vars/functions in overlays (especially those in scripts for browser.xul) need to be prefixed with an unique string. gFoo is used by everyone, gAsqueellaFoo is not likely to be used by anyone but me.



I just would like to know what you extension authors think about these issues. Extension writers tend to lack communication. Many of them do not post other than Q&A Topic.

TheOneKEA

User avatar
 
Posts: 4864
Joined: October 16th, 2003, 5:47 am
Location: Somewhere in London, riding the Underground

Post Posted October 8th, 2004, 4:29 am

Torisugari wrote:
TheOneKEA wrote:Does anybody write their JavaScript using the Linux kernel CodingStyle document?

Why linux kernel? It has nothing to do with javascript nor netscape. Take a look at Mozilla Coding Sytle Guideline.


Because I wrote C and C++ before I wrote JavaScript, and the CodingStyle document forms the basis of my entire coding style; I simply carried it over to JavaScript!

Torisugari wrote:I don't think everyone have to be compliant with this guideline. However, you'll have hard time when reading the moz source, if you don't know these rules at all.
http://lxr.mozilla.org/aviarybranch/search?string=gstr
http://lxr.mozilla.org/aviarybranch/search?string=aval
http://lxr.mozilla.org/aviarybranch/sea ... ing=this._

btw, overlay is another problem. rue, adblock has simple named overlay onto browser.xul, e.g. "console"...?
asqueella wrote:In order to prevent conflicts, global vars/functions in overlays (especially those in scripts for browser.xul) need to be prefixed with an unique string. gFoo is used by everyone, gAsqueellaFoo is not likely to be used by anyone but me.



I just would like to know what you extension authors think about these issues. Extension writers tend to lack communication. Many of them do not post other than Q&A Topic.


Every function that I write is prefixed with TBP_ to prevent namespace collisions. Every global variable that I write, either inside .js file scope or variable scope, is prefixed with two underscores to prevent namespace collisions. I consider this a Good Thing To Do.
Proud user of teh Fox of Fire
Registered Linux User #289618

Return to Mozilla Development


Who is online

Users browsing this forum: No registered users and 0 guests