Client-side
Server-side
About parens, braces and linebreaks.
1.
if ( condition ) {
// statements
}
Use whitespace to promote readability
2.
while ( condition ) {
// statements
}
4.
for ( var i = 0; i < 100; i++ ) {
// statements
}
3.
if ( condition ) {
// statements
} else {
// statements
}
About assignments, declarations and functions.
var test = "";
var bar = {};
var foo = [];
Using only one `var` per scope (function)
var test = "",
bar = {},
foo = [];
function foo() {
// statements here
var test = "",
bar;
}
function foo() {
var test = "",
bar;
// statements here }
1.
foo(function() {
// statement
});
Some exceptions
3. foo([ "Apple", "Samsung" ]);
2.
foo({
name: "Mike",
Age: 23
});
4.
foo("Apple");
5.
if ( (foo in bar) ) {
// statement
}
There is not difference in how JavaScript parses them
"What ABSOLUTELY MUST be enforced is consistency. Never mix quotes in the same project."
Whitespaces can ruin git diffs
1. typeof variable === "string"
2. typeof variable === "number"
3. typeof variable === "boolean"
4. typeof variable === "object"
7. variable === null
8. variable == null
5. typeof variable === "undefined"
6. variable === undefined
"1" === 1 // false
"1" == 1 // true
1. if ( array.length > 0 )
2. if ( array.length === 0 )
3. if ( string !== "" )
5. if ( foo === true )
6. if ( foo === false )
if ( array.length )
if ( !array.length )
if ( string )
4. if ( string === "" )
if ( !string )
if ( foo )
if ( !foo )
1. functionNamesLikeThis; // camelCase
2. variableNamesLikeThis; // camelCase
4. CONSTANTS_LIKE_THIS; // UPPERCASE
3. ConstructorNamesLikeThis; // PascalCase
If your not a human code compiler, please don't try to be one
function q(s) {
return document.querySelectorAll(s);
}
var i,a=[],els=q("#foo");
for(i=0;i<els.length;i++){a.push(els[i]);}
function query(selector) {
return document.querySelectorAll(selector);
}
var elements = [],
matches = query("#foo"),
length = matches.length;
for ( var i = 0; i < length; i++ ) {
elements.push( matches[i] );
}
Framework MVC JavaScript
var app = angular.module('app', [
'ngAnimate',
'ngRoute'
]);
Definition
angular
.module('app', [
'ngAnimate',
'ngRoute'
]);
Avoid
Recommended
var app = angular.module('app');
app.controller('SomeController', SomeController);
function SomeController() { }Getters
Avoid
Recommended
angular
.module('app')
.controller('SomeController', SomeController);
function SomeController() { }
angular
.module('app')
.controller('Dashboard', function() { })
.factory('logger', function() { });
Named vs Anonymous Functions
Avoid
Recommended
angular
.module('app')
.controller('Dashboard', Dashboard);
function Dashboard() { }
<div ng-controller="Customer">
{{ name }}
</div>
ControllerAs - View syntax
Avoid
Recommended
<div ng-controller="Customer as customer">
{{ customer.name }}
</div>
function Customer($scope) {
$scope.name = {};
$scope.sendMessage = function() { };
}
ControllerAs - Controller syntax
Avoid
Recommended
function Customer() {
this.name = {};
this.sendMessage = function() { };
}
function Customer() {
this.name = {};
this.sendMessage = function() { };
}
ControllerAs with vm
Avoid
Recommended
function Customer() {
var vm = this;
vm.name = {};
vm.sendMessage = function() { };
}
function Order($http, $q, config, userInfo) {
var vm = this;
vm.checkCredit = checkCredit;
vm.isCreditOk;
vm.total = 0;
function checkCredit() {
var settings = {};
return $http.get(settings)
.then(function(data) {
vm.isCreditOk = vm.total <= maxRemainingAmount
})
.catch(function(error) {
// Re-reject with appropriate error for a user to see
});
};
}
Defer Controller Logic to Services
Avoid
function Order(creditService) {
var vm = this;
vm.checkCredit = checkCredit;
vm.isCreditOk;
vm.total = 0;
function checkCredit() {
return creditService.isOrderTotalOk(vm.total)
.then(function(isOk) { vm.isCreditOk = isOk; })
.catch(showServiceError);
};
}
Defer Controller Logic to Services
Recommended
angular
.module('app')
.service('logger', logger);
function logger() {
this.logError = function(msg) {
/* */
};
}
Defer Controller Logic to Services
Service
angular
.module('app')
.factory('logger', logger);
function logger() {
return {
logError: function(msg) {
/* */
}
};
}
Factory
angular
.module('app.widgets')
/* directiva de órdenes que es específica del módulo de órdenes*/
.directive('orderCalendarRange', orderCalendarRange)
/* directiva de ventas que puede ser usada en algún otro lado a lo
largo de la aplicación de ventas */
.directive('salesCustomerInfo', salesCustomerInfo)
/* directiva de spinner que puede ser usada a lo largo de las
aplicaciones */
.directive('sharedSpinner', sharedSpinner);
Limit 1 Per File
Avoid
Limit 1 Per File
3.
var directive = {
restrict: 'EA',
templateUrl: 'exampleDirective.html',
controller: ExampleController,
controllerAs: 'vm',
};
4. <div class="my-calendar-range"></div>
Avoid
Recommended
4. <my-calendar-range></my-calendar-range> <div my-calendar-range></div>
Manually Identify Dependencies
angular
.module('app')
.controller('Dashboard',
['$location', '$routeParams', 'common', 'dataservice',
function Dashboard($location, $routeParams, common, dataservice) {}
]);
Avoid
Recommended
angular
.module('app')
.controller('Dashboard', Dashboard);
Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice'];
function Dashboard($location, $routeParams, common, dataservice) {
}
Unit testing helps maintain clean code
Testing Library
Test Runner
Use JSDoc and JSHint
/**
* @name logError
* @desc Logs errors
* @param {String} msg Message to log
* @returns {String}
* @memberOf Factories.Logger
*/
function logError(msg) {
var loggedMsg = 'Error: ' + msg;
$log.error(loggedMsg);
return loggedMsg;
};
JSDoc syntax
https://github.com/johnpapa/angular-styleguide/
AngularJS Sytle Guide
https://github.com/rwaldron/idiomatic.js
JavaScript Sytle Guide
http://usejsdoc.org/
JSDoc
http://jshint.com/
JSHint