- Переменные
- Объекты
- Массивы
- Строки
- Функции
- Итераторы и генераторы
- Операторы сравнения и равенства
- Блоки
- Пробелы
- Соглашения по именованию
- jQuery
Все примеры приводятся на ES6, чтобы им пользоваться уже сейчас, используйте Babel
Используйте
constдля всех переменных; избегайте использоватьvar.Почему? Это гарантирует, что вы не можете переназначить ваши переменные, которые могут привести к ошибкам и трудно понять код.
// Плохоvara=1;varb=2;// Хорошоconsta=1;constb=2;
Если вы должны переназначить переменную, то используйте
letвместоvar.// Плохоvarcount=1;if(true){count+=1;}// Хорошоletcount=1;if(true){count+=1;}
Используйте короткую запись создания объекта.
// Плохоconstitem=newObject();// Хорошоconstitem={};
Используйте короткую запись метода.
// Плохоconstatom={value: 1,addValue: function(value){returnatom.value+value;},};// Хорошоconstatom={value: 1,addValue(value){returnatom.value+value;},};
Не вызывайте методы
Object.prototypeнапрямую, например,hasOwnProperty,propertyIsEnumerable, andisPrototypeOf.
// Плохоconsole.log(object.hasOwnProperty(key));// Хорошоconsole.log(Object.prototype.hasOwnProperty.call(object,key));// Лучшеconsthas=Object.prototype.hasOwnProperty;// кешируется поиск/* или */consthas=require('has');…console.log(has.call(object,key));Используйте короткую запись создания массива.
// Плохоconstitems=newArray();// Хорошоconstitems=[];
Используйте метод push`, вместо прямого добавления элемента в массив.
constsomeStack=[];// ПлохоsomeStack[someStack.length]='abracadabra';// ХорошоsomeStack.push('abracadabra');
Используйте
...для копирования массива.// Плохоconstlen=items.length;constitemsCopy=[];leti;for(i=0;i<len;i++){itemsCopy[i]=items[i];}// ХорошоconstitemsCopy=[...items];
Используйте
returnв callback. Если функция состоит из одного оператора, тоreturnможно опустиить.// Хорошо[1,2,3].map((x)=>{consty=x+1;returnx*y;});// Хорошо[1,2,3].map(x=>x+1);// Плохоconstflat={};[[0,1],[2,3],[4,5]].reduce((memo,item,index)=>{constflatten=memo.concat(item);flat[index]=flatten;});// Хорошоconstflat={};[[0,1],[2,3],[4,5]].reduce((memo,item,index)=>{constflatten=memo.concat(item);flat[index]=flatten;returnflatten;});// Плохоinbox.filter((msg)=>{const{ subject, author }=msg;if(subject==='Mockingbird'){returnauthor==='Harper Lee';}else{returnfalse;}});// Хорошоinbox.filter((msg)=>{const{ subject, author }=msg;if(subject==='Mockingbird'){returnauthor==='Harper Lee';}returnfalse;});
Используйте одиночные ковычки
''для строк.// Плохоconstname="Capt. Janeway";// Плохоconstname=`Capt. Janeway`;// Хорошоconstname='Capt. Janeway';
Никогда не используй
eval(), это открывает слишком много уязвимостей.
Правильное объявление функции в блоке.
// Плохоif(currentUser){functiontest(){console.log('Nope.');}}// Хорошоlettest;if(currentUser){test=()=>{console.log('Yup.');};}
Используйте дефолтные аргументы, не изменяйте их.
// Очень плохоfunctionhandleThings(opts){// Нет! Нельзя изменять входящие программисты.// Если opts false, то переменная изменится// Это может привести к тонким ошибкам.opts=opts||{};// ...}// Все еще плохоfunctionhandleThings(opts){if(opts===void0){opts={};}// ...}// ХорошоfunctionhandleThings(opts={}){// ...}
Избегайте побочных эффектов.
varb=1;// Плохоfunctioncount(a=b++){console.log(a);}count();// 1count();// 2count(3);// 3count();// 3
Всегда дефолтные аргументы располагайте в конце.
// ПлохоfunctionhandleThings(opts={},name){// ...}// ХорошоfunctionhandleThings(name,opts={}){// ...}
Пробелы в функциях
// Плохоconstf=function(){};constg=function(){};consth=function(){};// Хорошоconstx=function(){};consty=functiona(){};
Никогда не переназначайте входные аргументы
// Плохоfunctionf1(a){a=1;}functionf2(a){if(!a){a=1;}}// Хорошоfunctionf3(a){constb=a||1;}functionf4(a=1){}
Не используйте итераторы. Используйте функции высшего порядка
for-inorfor-ofПочему? Чистые функции уменьшаются количество побочных эффектов.
Используйте
map()/every()/filter()/find()/findIndex()/reduce()/some()/ ... для перебора массива, иObject.keys()/Object.values()/Object.entries()для перебора массива и последующего создания массива.constnumbers=[1,2,3,4,5];// Плохоletsum=0;for(letnumofnumbers){sum+=num;}sum===15;// Хорошоletsum=0;numbers.forEach(num=>sum+=num);sum===15;// Лучшеconstsum=numbers.reduce((total,num)=>total+num,0);sum===15;
Не используйте генераторы
Если вам нужно использовать генераторы, но все равно не рекомендуем.
// Плохоfunction*foo(){}constbar=function*(){}constbaz=function*(){}constquux=function*(){}function*foo(){}function*foo(){}// Очень плохоfunction*foo(){}constwat=function*(){}// Хорошоfunction*foo(){}constfoo=function*(){}
Используйте
===and!==вместо==and!=Используйте корткую запись.
// Плохоif(name!==''){// ...stuff...}// Хорошоif(name){// ...stuff...}// Плохоif(collection.length>0){// ...stuff...}// Хорошоif(collection.length){// ...stuff...}
Тернарное выражение не должно быть вложенным.
// Плохоconstfoo=maybe1>maybe2 ? "bar" : value1>value2 ? "baz" : null;// ЛучшеconstmaybeNull=value1>value2 ? 'baz' : null;constfoo=maybe1>maybe2 ? 'bar' : maybeNull;// ХорошоconstmaybeNull=value1>value2 ? 'baz' : null;constfoo=maybe1>maybe2 ? 'bar' : maybeNull;
Избегайте ненужных тернарных выражений.
// Плохоconstfoo=a ? a : b;constbar=c ? true : false;constbaz=c ? false : true;// Хорошоconstfoo=a||b;constbar=!!c;constbaz=!c;
Используйте фигурные скобки.
// Плохоif(test)returnfalse;// Хорошоif(test)returnfalse;// Хорошоif(test){returnfalse;}// Плохоfunctionfoo(){returnfalse;}// Хорошоfunctionbar(){returnfalse;}
Для отступа используйте 2 пробелы.
// Плохоfunctionfoo(){∙∙∙∙constname;}// Плохоfunctionbar(){∙constname;}// Хорошоfunctionbaz(){∙∙constname;}
Должен быть 1 пробел перед открывающей фигурной скобки
// Плохоfunctiontest(){console.log('test');}// Хорошоfunctiontest(){console.log('test');}// Плохоdog.set('attr',{age: '1 year',breed: 'Bernese Mountain Dog',});// Хорошоdog.set('attr',{age: '1 year',breed: 'Bernese Mountain Dog',});
Должен быть 1 пробел перед открывающей скобкой, кроме списком аргуметнов и имени функции.
// Плохоif(isJedi){fight();}// Хорошоif(isJedi){fight();}// Плохоfunctionfight(){console.log('Swooosh!');}// Хорошоfunctionfight(){console.log('Swooosh!');}
Отделяйте операторы пробелом.
// Плохоconstx=y+5;// Хорошоconstx=y+5;
Используйте отступы при создании цепочки методов.
// Плохо$('#items').find('.selected').highlight().end().find('.open').updateCount();// Плохо$('#items').find('.selected').highlight().end().find('.open').updateCount();// Хорошо$('#items').find('.selected').highlight().end().find('.open').updateCount();// Плохоconstleds=stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led',true).attr('width',(radius+margin)*2).append('svg:g').attr('transform','translate('+(radius+margin)+','+(radius+margin)+')').call(tron.led);// Хорошоconstleds=stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led',true).attr('width',(radius+margin)*2).append('svg:g').attr('transform','translate('+(radius+margin)+','+(radius+margin)+')').call(tron.led);// Хорошоconstleds=stage.selectAll('.led').data(data);
Оставьте пустую строку после блоков.
// Плохоif(foo){returnbar;}returnbaz;// Хорошоif(foo){returnbar;}returnbaz;// Плохоconstobj={foo(){},bar(){},};returnobj;// Хорошоconstobj={foo(){},bar(){},};returnobj;// Плохоconstarr=[functionfoo(){},functionbar(){},];returnarr;// Хорошоconstarr=[functionfoo(){},functionbar(){},];returnarr;
Не начинайте с пустой строки в блоке.
// Плохоfunctionbar(){console.log(foo);}// Плохоif(baz){console.log(qux);}else{console.log(foo);}// Хорошоfunctionbar(){console.log(foo);}// Хорошоif(baz){console.log(qux);}else{console.log(foo);}
Не добавляйте пробелы внутри скобок.
// Плохоfunctionbar(foo){returnfoo;}// Хорошоfunctionbar(foo){returnfoo;}// Плохоif(foo){console.log(foo);}// Хорошоif(foo){console.log(foo);}// Плохоconstfoo=[1,2,3];console.log(foo[0]);// Хорошоconstfoo=[1,2,3];console.log(foo[0]);
Добавить пробелы в фигурные скобки.
// Плохоconstfoo={clark: 'kent'};// Хорошоconstfoo={clark: 'kent'};
Избегайте строк кода, которые длиннее 100 символов (включая пробелы).
// Плохоconstfoo=jsonData&&jsonData.foo&&jsonData.foo.bar&&jsonData.foo.bar.baz&&jsonData.foo.bar.baz.quux&&jsonData.foo.bar.baz.quux.xyzzy;// Плохо$.ajax({method: 'POST',url: 'https://airbnb.com/',data: {name: 'John'}}).done(()=>console.log('Congratulations!')).fail(()=>console.log('You have failed this city.'));// Хорошоconstfoo=jsonData&&jsonData.foo&&jsonData.foo.bar&&jsonData.foo.bar.baz&&jsonData.foo.bar.baz.quux&&jsonData.foo.bar.baz.quux.xyzzy;// Хорошо$.ajax({method: 'POST',url: 'https://airbnb.com/',data: {name: 'John'},}).done(()=>console.log('Congratulations!')).fail(()=>console.log('You have failed this city.'));
Избегайте одиночные названия букв.
// Плохоfunctionq(){// ...stuff...}// Хорошоfunctionquery(){// ..stuff..}
Используйте CamelCase при именовании объектов, функций, а также переменных.
// ПлохоconstOBJEcttsssss={};constthis_is_my_object={};functionc(){}// ХорошоconstthisIsMyObject={};functionthisIsMyFunction(){}
Используйте PascalCase только при именовании конструкторов или классов.
// Плохоfunctionuser(options){this.name=options.name;}constbad=newuser({name: 'nope',});// ХорошоclassUser{constructor(options){this.name=options.name;}}constgood=newUser({name: 'yup',});
Используйте префик
$в переменных, где лежит объект jQuery.// Плохоconstsidebar=$('.sidebar');// Хорошоconst$sidebar=$('.sidebar');// Хорошоconst$sidebarBtn=$('.sidebar-btn');
25.2 Cache jQuery.
// ПлохоfunctionsetSidebar(){$('.sidebar').hide();// ...stuff...$('.sidebar').css({'background-color': 'pink'});}// ХорошоfunctionsetSidebar(){const$sidebar=$('.sidebar');$sidebar.hide();// ...stuff...$sidebar.css({'background-color': 'pink'});}
Используйте find с умом.
// Плохо$('ul','.sidebar').hide();// Плохо$('.sidebar').find('ul').hide();// Хорошо$('.sidebar ul').hide();// Хорошо$('.sidebar > ul').hide();// Хорошо$sidebar.find('ul').hide();