GitHub - programaelfuturo/javascript-style-guide: Guía de Estilo en JavaScript
**[[⬆]](#TOC)**
## <a name='whitespace'>Espacios en blanco</a>
- Usa indentaciones blandas (sin TAB) establecidas en dos espacios.
```javascript
// mal
function() {
∙∙∙∙var name;
}
// mal
function() {
∙var name;
}
// bien
function() {
∙∙var name;
}
```
- Deja un espacio antes de la llave de apertura.
```javascript
// mal
function test(){
console.log('test');
}
// bien
function test() {
console.log('test');
}
// mal
dog.set('attr',{
age: '1 year',
breed: 'Bernese Mountain Dog'
});
// bien
dog.set('attr', {
age: '1 year',
breed: 'Bernese Mountain Dog'
});
```
- Deja una línea en blanco al final del archivo.
```javascript
// mal
(function(global) {
// ...algo...
})(this);
```
```javascript
// bien
(function(global) {
// ...algo...
})(this);
```
- Usa indentación cuando uses métodos largos con 'chaining'.
```javascript
// mal
$('#items').find('.selected').highlight().end().find('.open').updateCount();
// bien
$('#items')
.find('.selected')
.highlight()
.end()
.find('.open')
.updateCount();
// mal
var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true)
.attr('width', (radius + margin) * 2).append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
// bien
var leds = stage.selectAll('.led')
.data(data)
.enter().append('svg:svg')
.class('led', true)
.attr('width', (radius + margin) * 2)
.append('svg:g')
.attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
.call(tron.led);
```
**[[⬆]](#TOC)**
## <a name='commas'>Comas</a>
- Comas al inicio de línea: **Nop.**
```javascript
// mal
var once
, upon
, aTime;
// bien
var once,
upon,
aTime;
// mal
var hero = {
firstName: 'Bob'
, lastName: 'Parr'
, heroName: 'Mr. Incredible'
, superPower: 'strength'
};
// bien
var hero = {
firstName: 'Bob',
lastName: 'Parr',
heroName: 'Mr. Incredible',
superPower: 'strength'
};
```
- Coma adicional al final: **Nop.** Esto puede provocar problemas en IE6/7 o IE9 si está en quirksmode. Además, en algunas implementaciones de ES3 se puede aumentar la longitud del arreglo si se tiene una coma adicional al final. Esto fue clarificado en ES5 ([fuente](http://es5.github.io/#D)):
> La Edición 5 aclara el hecho de que dejar una coma al final de un ArrayInitialiser (inicialización de un arreglo) no aumenta la longitud del arreglo. Esto no es un cambio semántico a la Edición 3 pero algunas implementaciones tal vez malinterpretaron esto.
```javascript
// mal
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
var heroes = [
'Batman',
'Superman',
];
// bien
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
var heroes = [
'Batman',
'Superman'
];
```
**[[⬆]](#TOC)**
## <a name='semicolons'>Puntos y Comas</a>
- **Sip.**
```javascript
// mal
(function() {
var name = 'Skywalker'
return name
})()
// bien
(function() {
var name = 'Skywalker';
return name;
})();
// bien
;(function() {
var name = 'Skywalker';
return name;
})();
```
**[[⬆]](#TOC)**
## <a name='type-coercion'>Casting de Tipos & Coerción</a>
- Ejecuta coerción al inicio de una sentencia.
- Strings:
```javascript
// => this.reviewScore = 9;
// mal
var totalScore = this.reviewScore + '';
// bien
var totalScore = '' + this.reviewScore;
// mal
var totalScore = '' + this.reviewScore + ' total score';
// bien
var totalScore = this.reviewScore + ' total score';
```
- Usa `parseInt` para números y siempre con la base numérica para el casting de tipo.
```javascript
var inputValue = '4';
// mal
var val = new Number(inputValue);
// mal
var val = +inputValue;
// mal
var val = inputValue >> 0;
// mal
var val = parseInt(inputValue);
// bien
var val = Number(inputValue);
// bien
var val = parseInt(inputValue, 10);
```
- Si por alguna razón estás haciendo algo salvaje y `parseInt` es un cuello de botella por lo que necesitaste usar Bitshift por [razones de desempeño](http://jsperf.com/coercion-vs-casting/3), deja un comentario explicando qué y porqué lo estás haciendo.
```javascript
// bien
/**
* parseInt was the reason my code was slow.
* Bitshifting the String to coerce it to a
* Number made it a lot faster.
*/
var val = inputValue >> 0;
```
- Booleans:
```javascript
var age = 0;
// mal
var hasAge = new Boolean(age);
// bien
var hasAge = Boolean(age);
// bien
var hasAge = !!age;
```
**[[⬆]](#TOC)**
## <a name='naming-conventions'>Convenciones de nomenclatura</a>
- Evita nombres de una sola letra. Sé descriptivo con tus nombres.
```javascript
// mal
function q() {
// ...algo...
}
// bien
function query() {
// ...algo...
}
```
- Usa camelCase cuando nombres tus objetos, funciones e instancias.
```javascript
// mal
var OBJEcttsssss = {};
var this_is_my_object = {};
var this-is-my-object = {};
function c() {};
var u = new user({
name: 'Bob Parr'
});
// bien
var thisIsMyObject = {};
function thisIsMyFunction() {};
var user = new User({
name: 'Bob Parr'
});
```
- Usa PascalCase cuando nombres constructores o clases.
```javascript
// mal
function user(options) {
this.name = options.name;
}
var bad = new user({
name: 'nope'
});
// bien
function User(options) {
this.name = options.name;
}
var good = new User({
name: 'yup'
});
```
- Usa un guión bajo `_` adelante de la variable cuando nombres propiedades privadas.
```javascript
// mal
this.__firstName__ = 'Panda';
this.firstName_ = 'Panda';
// bien
this._firstName = 'Panda';
```
- Cuando guardes una referencia a `this` usa `_this`.
```javascript
// mal
function() {
var self = this;
return function() {
console.log(self);
};
}
// mal
function() {
var that = this;
return function() {
console.log(that);
};
}
// bien
function() {
var _this = this;
return function() {
console.log(_this);
};
}
```
- Nombra tus funciones. Esto será de ayuda cuando hagas seguimiento de la pila de llamadas (e.g. en caso de errores).
```javascript
// mal
var log = function(msg) {
console.log(msg);
};
// bien
var log = function log(msg) {
console.log(msg);
};
```
**[[⬆]](#TOC)**
## <a name='accessors'>Funciones de Acceso</a>
- Funciones de acceso para las propiedades no son requeridas.
- Si creas funciones de acceso usa getVal() y setVal('hello').
```javascript
// mal
dragon.age();
// bien
dragon.getAge();
// mal
dragon.age(25);
// bien
dragon.setAge(25);
```
- Si la propiedad es un booleano, usa isVal() o hasVal().
```javascript
// mal
if (!dragon.age()) {
return false;
}
// bien
if (!dragon.hasAge()) {
return false;
}
```
- Está bien crear funciones get() y set(), pero sé consistente.
```javascript
function Jedi(options) {
options || (options = {});
var lightsaber = options.lightsaber || 'blue';
this.set('lightsaber', lightsaber);
}
Jedi.prototype.set = function(key, val) {
this[key] = val;
};
Jedi.prototype.get = function(key) {
return this[key];
};
```
**[[⬆]](#TOC)**
## <a name='constructors'>Constructores</a>
- Asigna métodos al objeto prototype, en vez de sobreescribir prototype con un nuevo objeto. La sobreescritura de prototype hace la herencia imposible: ¡reseteando prototype sobreescribirás la base!
```javascript
function Jedi() {
console.log('new jedi');
}
// mal
Jedi.prototype = {
fight: function fight() {
console.log('fighting');
},
block: function block() {
console.log('blocking');
}
};
// bien
Jedi.prototype.fight = function fight() {
console.log('fighting');
};
Jedi.prototype.block = function block() {
console.log('blocking');
};
```
- Métodos pueden retornar `this` para ayudar con el encadenamiento de métodos (chaining).
```javascript
// mal
Jedi.prototype.jump = function() {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
};
var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20) // => undefined
// bien
Jedi.prototype.jump = function() {
this.jumping = true;
return this;
};
Jedi.prototype.setHeight = function(height) {
this.height = height;
return this;
};
var luke = new Jedi();
luke.jump()
.setHeight(20);
```
- Está bien escribir un método toString() personalizado, solo asegúrate que funcione correctamente y no cause efectos colaterales.
```javascript
function Jedi(options) {
options || (options = {});
this.name = options.name || 'no name';
}
Jedi.prototype.getName = function getName() {
return this.name;
};
Jedi.prototype.toString = function toString() {
return 'Jedi - ' + this.getName();
};
```
**[[⬆]](#TOC)**
## <a name='events'>Eventos</a>
- Cuando envies paquetes de datos a los eventos (ya sea con eventos del DOM o algo propietario como los eventos de Backbone), pasa un mapa en vez de un valor directo. Esto permitirá a un próximo colaborador a agregar más datos al paquete de datos sin que tenga que encontrar o actualizar un handler para cada evento. Por ejemplo, en vez de:
```js
// mal
$(this).trigger('listingUpdated', listing.id);
...
$(this).on('listingUpdated', function(e, listingId) {
// hacer algo con listingId
});
```
prefiere:
```js
// bien
$(this).trigger('listingUpdated', { listingId : listing.id });
...
$(this).on('listingUpdated', function(e, data) {
// hacer algo con data.listingId
});
```
**[[⬆]](#TOC)**
## <a name='modules'>Módulos</a>
- El módulo debe empezar con un `!`. Esto asegura que si un módulo mal formado olvide incluir al final un punto y coma, no hayan errores en producción cuando los scripts sean concatenados. [Explicación](https://github.com/airbnb/javascript/issues/44#issuecomment-13063933)
- El archivo debe ser nombrado con camelCase, residir en un folder con el mismo nombre, y corresponder al nombre de la función a exportar.
- Agrega un método noConflict() que reestablezca el módulo exportado a la versión anterior y retorne este módulo (para ser asignado a una variable).
- Siempre declara `'use strict';` al inicio de cada módulo.
```javascript
// fancyInput/fancyInput.js
!function(global) {
'use strict';
var previousFancyInput = global.FancyInput;
function FancyInput(options) {
this.options = options || {};
}
FancyInput.noConflict = function noConflict() {
global.FancyInput = previousFancyInput;
return FancyInput;
};
global.FancyInput = FancyInput;
}(this);
```
**[[⬆]](#TOC)**
## <a name='jquery'>jQuery</a>
- Nombre las variables de objetos jQuery con un prefijo `$`.
```javascript
// mal
var sidebar = $('.sidebar');
// bien
var $sidebar = $('.sidebar');
```
- Guarde en variables los lookups de jQuery que se necesiten posteriormente.
```javascript
// mal
function setSidebar() {
$('.sidebar').hide();
// ...algo...
$('.sidebar').css({
'background-color': 'pink'
});
}
// bien
function setSidebar() {
var $sidebar = $('.sidebar');
$sidebar.hide();
// ...algo...
$sidebar.css({
'background-color': 'pink'
});
}
```
- Para consultas de elementos DOM usa el modo Cascada `$('.sidebar ul')` o parent > child `$('.sidebar > ul')`. [jsPerf](http://jsperf.com/jquery-find-vs-context-sel/16)
- Usa `find` solo con consultas guardadas en variables previamente.
```javascript
// mal
$('ul', '.sidebar').hide();
// mal
$('.sidebar').find('ul').hide();
// bien
$('.sidebar ul').hide();
// bien
$('.sidebar > ul').hide();
// bien
$sidebar.find('ul');
```
**[[⬆]](#TOC)**
## <a name='es5'>Compatibilidad con ECMAScript 5</a>
- Revisa la [tabla de compatibilidad](http://kangax.github.com/es5-compat-table/) de ES5 de [Kangax](https://twitter.com/kangax/).
**[[⬆]](#TOC)**
## <a name='testing'>Pruebas</a>
- **Sip**.
```javascript
function() {
return true;
}
```
**[[⬆]](#TOC)**
## <a name='performance'>Desempeño</a>
- [On Layout & Web Performance](http://kellegous.com/j/2013/01/26/layout-performance/)
- [String vs Array Concat](http://jsperf.com/string-vs-array-concat/2)
- [Try/Catch Cost In a Loop](http://jsperf.com/try-catch-in-loop-cost)
- [Bang Function](http://jsperf.com/bang-function)
- [jQuery Find vs Context, Selector](http://jsperf.com/jquery-find-vs-context-sel/13)
- [innerHTML vs textContent for script text](http://jsperf.com/innerhtml-vs-textcontent-for-script-text)
- [Long String Concatenation](http://jsperf.com/ya-string-concat)
- Loading...
**[[⬆]](#TOC)**
## <a name='resources'>Recursos</a>
**Lee esto**
- [Annotated ECMAScript 5.1](http://es5.github.com/)
**Otras guías de estilo**
- [Google JavaScript Style Guide](http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml)
- [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
- [Principles of Writing Consistent, Idiomatic JavaScript](https://github.com/rwldrn/idiomatic.js/)
**Otros estilos**
- [Naming this in nested functions](https://gist.github.com/4135065) - Christian Johansen
- [Conditional Callbacks](https://github.com/airbnb/javascript/issues/52)
**Lectura más profunda**
- [Understanding JavaScript Closures](http://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/) - Angus Croll
**Libros**
- [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) - Douglas Crockford
- [JavaScript Patterns](http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752) - Stoyan Stefanov
- [Pro JavaScript Design Patterns](http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X) - Ross Harmes and Dustin Diaz
- [High Performance Web Sites: Essential Knowledge for Front-End Engineers](http://www.amazon.com/High-Performance-Web-Sites-Essential/dp/0596529309) - Steve Souders
- [Maintainable JavaScript](http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680) - Nicholas C. Zakas
- [JavaScript Web Applications](http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X) - Alex MacCaw
- [Pro JavaScript Techniques](http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273) - John Resig
- [Smashing Node.js: JavaScript Everywhere](http://www.amazon.com/Smashing-Node-js-JavaScript-Everywhere-Magazine/dp/1119962595) - Guillermo Rauch
- [Secrets of the JavaScript Ninja](http://www.amazon.com/Secrets-JavaScript-Ninja-John-Resig/dp/193398869X) - John Resig and Bear Bibeault
- [Human JavaScript](http://humanjavascript.com/) - Henrik Joreteg
- [Superhero.js](http://superherojs.com/) - Kim Joar Bekkelund, Mads Mobæk, & Olav Bjorkoy
**Blogs**
- [DailyJS](http://dailyjs.com/)
- [JavaScript Weekly](http://javascriptweekly.com/)
- [JavaScript, JavaScript...](http://javascriptweblog.wordpress.com/)
- [Bocoup Weblog](http://weblog.bocoup.com/)
- [Adequately Good](http://www.adequatelygood.com/)
- [NCZOnline](http://www.nczonline.net/)
- [Perfection Kills](http://perfectionkills.com/)
- [Ben Alman](http://benalman.com/)
- [Dmitry Baranovskiy](http://dmitry.baranovskiy.com/)
- [Dustin Diaz](http://dustindiaz.com/)
- [nettuts](http://net.tutsplus.com/?s=javascript)
**[[⬆]](#TOC)**
## <a name='in-the-wild'>En la cancha</a>
Esta es una lista de las organizaciones que están usando esta guía de estilo. Envíanos un pull request o abre un issue y te agregaremos a la lista.
- **Airbnb**: [airbnb/javascript](https://github.com/airbnb/javascript)
- **American Insitutes for Research**: [AIRAST/javascript](https://github.com/AIRAST/javascript)
- **Compass Learning**: [compasslearning/javascript-style-guide](https://github.com/compasslearning/javascript-style-guide)
- **ExactTarget**: [ExactTarget/javascript](https://github.com/ExactTarget/javascript)
- **GeneralElectric**: [GeneralElectric/javascript](https://github.com/GeneralElectric/javascript)
- **GoodData**: [gooddata/gdc-js-style](https://github.com/gooddata/gdc-js-style)
- **Grooveshark**: [grooveshark/javascript](https://github.com/grooveshark/javascript)
- **How About We**: [howaboutwe/javascript](https://github.com/howaboutwe/javascript)
- **MinnPost**: [MinnPost/javascript](https://github.com/MinnPost/javascript)
- **ModCloth**: [modcloth/javascript](https://github.com/modcloth/javascript)
- **National Geographic**: [natgeo/javascript](https://github.com/natgeo/javascript)
- **National Park Service**: [nationalparkservice/javascript](https://github.com/nationalparkservice/javascript)
- **Razorfish**: [razorfish/javascript-style-guide](https://github.com/razorfish/javascript-style-guide)
- **Shutterfly**: [shutterfly/javascript](https://github.com/shutterfly/javascript)
- **Userify**: [userify/javascript](https://github.com/userify/javascript)
- **Zillow**: [zillow/javascript](https://github.com/zillow/javascript)
- **ZocDoc**: [ZocDoc/javascript](https://github.com/ZocDoc/javascript)
## <a name='translation'>Traducciones</a>
Esta guía de estilo es también disponible en otros lenguajes:
- :de: **Alemán**: [timofurrer/javascript-style-guide](https://github.com/timofurrer/javascript-style-guide)
- :jp: **Japonés**: [mitsuruog/javacript-style-guide](https://github.com/mitsuruog/javacript-style-guide)
- :br: **Portugués**: [armoucar/javascript-style-guide](https://github.com/armoucar/javascript-style-guide)
- :cn: **Chino**: [adamlu/javascript-style-guide](https://github.com/adamlu/javascript-style-guide)
## <a name='guide-guide'>La guía de la Guía de Estilos de Javascript</a>
- [Referencia](https://github.com/airbnb/javascript/wiki/The-JavaScript-Style-Guide-Guide)
## <a name='authors'>Colaboradores</a>
- [Vea a los colaboradores](https://github.com/airbnb/javascript/graphs/contributors)
## <a name='license'>Licencia</a>
(The MIT License)
Copyright (c) 2012 Airbnb
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**[[⬆]](#TOC)**
# };