JavaScript Coding Conventions
IMPORTANT: THIS IS A BETA VERSION
It is under active development and may contain unstable or incomplete features. Use it at your own risk.
Overview
This document is based on Google's JavaScript Style Guide and Douglas Crockford's Code Conventions for the JavaScript Programming Language.
Linting and Formatting
Info
To use these new tools, it is required to have nodejs/npm installed in your machine.
ESLint and Prettier are the tools used in Etendo to format check Javascript code. For convenience, has bundled some scripts in order to use these tools, either as standalone scripts and as Mercurial hooks to check the code before commiting it.
Standalone scripts
-
ESLint:
Running the jslint script without parameters passes the linter to all non-ignored .js files in the project, scanning first the files in core and all modules that has no special ignore rules (i.e. that has a .eslintignore file in the root of the module).
Adding the -f flag, ESLint will try to fix all warnings/errors that can be autofixed:
Finally, one or more files paths can be added to run ESLint for those specific files.
-
Prettier:
Running the jsformatter script without parameters passes the formatter to all non-ignored .js files in the project, scanning first the files in core and all modules that has no special ignore rules (i.e. that has a .prettierignore file in the root of the module).
Adding the -w flag, instead of checking whether the files are formatted, performs the actual formatting and writes them in their corresponding files:
Finally, one or more files paths can be added to run Prettier for those specific files.
Running npm script directly
Note that if your IDE supports npm, the following can be used as well to check your code:
-
ESLint
-
Prettier:
npm run jsformat -- --check modules/org.openbravo.client.application/web/org.openbravo.client.application/js/utilities/ob-utilities.jsor, if you want to check a whole module:
Git hooks
For using these tools as Git hooks, run this command from inside an openbravo repository:
To hook this script to another repository, copy the .gitHooks to that repo and run the same command.
If you want this hooks in external/retail modules, **from inside modules/
Note
Those scripts use realpath bash command to check between staged andunstaged changes. If not installed(it is by default on most systems) hooks will only check files in their current state, not differentiating between staged and unstaged changes.
Set hooks globally
It is possible to set those git hooks globally for all git repositories. This means .githooks will be executed on any commit in all your git repositories locally.
Example (assuming myHooks dir contains .githooks):
If for any reason you want to remove this configuration execute the following:
Code Formatting
Info
Javascript code is formatted using Prettier. The following conventions apply, but check Prettier rationale for some of the choices regarding formatting.
Spaces instead of Tabs
Configure your editor to use 2 spaces instead of tabs .
Curly Braces
Because of implicit semicolon insertion, always start your curly braces on the same line as whatever they're opening. For example:
Variable Declaration
A single var statement is preferred. All the variables in a function must be declared on top of the function.
Note
Why do I need to declare the variables on top of the function? Check JavaScript Hosting explained.
It is a good coding practice to initialize variables when you declare them. So we must declare and initialize in one coding line all vars of the function. Using this convention we will define all vars at the top of the function and we will "set" the type of the var adding more info to it.
function f() {
var a = 0,
b = '',
c = null;
}
function f() {
var i = 0, j = 1; // Just one var
// {...}
}
function x() {
var i = 0; // one var statement per variable is discouraged
var j = 0;
// {...}
}
// Variables on top of the function
function z() {
var i, j, k;
// {...}
}
function s() {
var i;
for (i = 0; i < 10; i++) {
// do something
}
// {...}
var j; // Variable declaration in the middle of a function is discouraged
}
Array and Object Initializers
Single-line array and object initializers are allowed when they fit on a line:
var arr = [1, 2, 3]; // No space after [ or before ].
var obj = {a: 1, b: 2, c: 3}; // No space after { or before }.
Multiline array initializers and object initializers are indented 2 spaces, just like blocks.
// Object initializer.
var inset = {
top: 10, // Notice the space after the colon
right: 20,
bottom: 15,
left: 12
};
// Array initializer.
this.rows_ = [
'"Slartibartfast" <fjordmaster@magrathea.com>',
'"Zaphod Beeblebrox" <theprez@universe.gov>',
'"Ford Prefect" <ford@theguide.com>',
'"Arthur Dent" <has.no.tea@gmail.com>',
'"Marvin the Paranoid Android" <marv@googlemail.com>',
'the.mice@magrathea.com'
];
// Used in a method call.
OB.ViewManager.openView('_140', {
command: 'DEFAULT'
icon: 'Window'
id: '180'
tabId: '180'
tabTitle: 'Product'
viewId: '_140'
windowId: '140'
});
Single Quotes
A string can be defined with single or double quotes. For consistency, single quotes are preferred.
Function Declaration
All functions should be declared before they are used. Inner functions should follow the var statement. This helps make it clear what variables are included in its scope.
There should be no space between the name of a function and the ( (left parenthesis) of its parameter list. There should be one space between the ) (right parenthesis) and the { (left curly brace) that begins the statement body. The body itself is indented four spaces. The } (right curly brace) is aligned with the line containing the beginning of the declaration of the function.
function outer(c, d) {
var e = c * d;
function inner(a, b) {
return (e * a) + b;
}
return inner(0, 1);
}
If a function literal is anonymous, there should be one space between the word function and the ( (left parenthesis). If the space is omitted, then it can appear that the function's name is function, which is an incorrect reading.
Function Arguments
When possible, all function arguments should be listed on the same line. If doing so would exceed the 100-column limit, the arguments must be line-wrapped in a readable way. To save space, you may wrap as close to 100 as possible, or put each argument on its own line to enhance readability. The indentation may be either four spaces, or aligned to the parenthesis.
// Four-space, wrap at 100. Works with very long function names, survives
// renaming without reindenting, low on space.
OB.foo.bar.doThingThatIsVeryDifficultToExplain = function (
veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
};
// Four-space, one argument per line. Works with long function names,
// survives renaming, and emphasizes each argument.
OB.foo.bar.doThingThatIsVeryDifficultToExplain = function (
veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
};
// Parenthesis-aligned indentation, wrap at 80. Visually groups arguments,
// low on space.
function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
}
// Parenthesis-aligned, one argument per line. Visually groups and
// emphasizes each individual argument.
function bar(veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
}
Naming files
Files name must be only in lower case and dash to separate words. Some servers are not case sensitive and spaces are a bad idea.
Example:
Wrong: LoginModel.js, cashUpWIndow.js...
Right: login-model.js, cashup-window.js...
Return object
Functions which returns an object will return a variable instead of the object. Returning a variable well named will help us to understand better what is returned (together with the function name) and will be also more readable. There is no need of creating a variable to return if we won't "work" with that object. Coding, we usually create a var to return because we will assign some values to that object but if the functions will return a new object we can do it directly, see some examples:
function myFunction (){
var myObject = {};
myObject.time = new Date();
myObject.total = getNet() + getTax();
if(total > 0){
myObject.isNegative = false;
}else {
myObject.isNegative = true;
}
return myObject;
}
function myFunction (){
return {name: getName(), address: getDefaultAddress() + getCountry()};
}
Tips and Tricks
True and False Boolean Expressions
The following are all false in boolean expressions:
But be careful, because these are all true :
This means that instead of this:
you can write this shorter code (as long as you don't expect x to be 0, or the empty string, or false):
And if you want to check a string to see if it is null or empty, you could do this:
But this is shorter and nicer:
Warning
There are many unintuitive things about boolean expressions. Here are some of them:
Conditional (Ternary) Operator
Instead of this:
you can write this:
AND and OR Operators
These binary boolean operators are short-circuited, and evaluate to the last evaluated term. || has been called the 'default' operator, because instead of writing this:
you can write this:
** && ** is also useful for shortening code. For instance, instead of this:
you could do this:
or this:
This work is a derivative of Javascript Coding Conventions by Openbravo Wiki, used under CC BY-SA 2.5 ES. This work is licensed under CC BY-SA 2.5 by Etendo.