Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 5 years have passed since last update.
JavaScriptは大変難しい言語です。Rubyの難易度を2、Cの難易度を5、C++の難易度を8にすると、JavaScriptの難易度は12ぐらいあると思います。このコーディングガイドはそんなJavaScriptの深みに嵌まらないようにするためのJavaScriptの書き方を規定したものです。初級者1のための物ですので、わかってやっている人に好きにやってください。
このコーディングガイドは絶対に従わなければならないものではありません。私は一切強制はしませんし、初級者が従わなければならないという義務もありません。採用するしないはみなさんの自由です。
禁止編
JavaScriptには安易に使用してはいけない機能があります。下記の機能は、**それぞれの機能を使っても良い、または、使うべきであるという理由を説明できない限り、**使用してはいけません。

==、!=
==と!=を使用してはいけません。代わりに===や!==を使用し、必要に応じて型変換を行ってください。
constx='1';if(x==1){console.log('xは1です。');}constx='1';if(Number(x)===1){console.log('xは1です。');}例外は、x != nullでnullまたはundefinedで無い事をチェックする(存在チェック)ことです。
constx='1';if(x!=null){console.log('xは存在します。');}
var
varを使用してはいけません。代わりにletやconstを使用してください。
varx=1;vary=2;x=3;letx=1;consty=2;x=3;
関数宣言、ジェネレーター宣言、非同期関数宣言
関数宣言、ジェネレーター宣言、非同期関数宣言を使用してはいけません。関数を定義する場合は、関数式またはジェネレーター式、非同期関数式、アロー関数、非同期アロー関数をconst変数に代入してください。
functionhelloOne(ok){// 厳格モードと非厳格モードでifブロック内の動作が異なるif(ok){functionhello(){console.log('こんにちは');}}else{functionhello(){console.log('世界');}}function*one(){yield1;}hello();for(constvofone()){console.log(v);}}helloOne(true);consthelloOne=(ok)=>{lethello;if(ok){hello=()=>{console.log('こんにちは');};}else{hello=()=>{console.log('世界');};}constone=function*(){yield1;};hello();for(constvofone()){console.log(v);}};helloOne(true);何らかの理由でvarおよび関数宣言を使用する場合は、巻き上げと変更可能であることを十分理解していなければなりません。下記のコードの実行結果が予測ができる状態でなければなりません。
varhello=function(){console.log('世界!');};functionhello(){console.log('こんにちは');}hello();クラスおよびメソッドは、式にしなければならない理由が無い限り宣言にしてください。
classPerson{constructor(name,age){this.name=name;this.age=age;}isAdult(){if(this.age>=20){returntrue;}else{returnfalse;}}}関数式、ジェネレーター式、非同期関数式でコード内にthisが含まれる場合はthisがレキシカルに決定されない事を理解しておく必要があります。この文章の意味がわからなければ、使用すべきではありません。
constf=function(){console.log(this);console.log(this.x);};f();// undefinedconstobj={x:42,f:f};obj.f();// 42
コールバックに関数式 (thisが明確な場合を除く)
コールバックに関数式を使用してはいけません。代わりにアロー関数を使用してください。
classCalculator{constructor(number){this.number=number;}allAdd(arr){returnarr.map(function(n){// thisがundefinedになり、エラーreturnn+this.number;});}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);classCalculator{constructor(number){this.number=number;}allAdd(arr){returnarr.map(n=>n+this.number);}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);thisを明確に指定している、または、渡す関数側でthisが束縛されるオブジェクトが明確かつ使用される、thisを使用していないという場合は、関数式を使用してもかまいません。
classCalculator{constructor(number){this.number=number;}allAdd(arr){returnarr.map(function(n){returnn+this.number;},this);// map()は第二引数でthisを指定可能}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);再帰関数を作る場合は、関数式を使用してもかまいません。ただし、thisに対する注意事項は理解した上で、という条件が付きます。
constlist=[2,3,5,7,11]constcollatzCountList=list.map(functioncollatzCount(num,idx,arr,count=0){if(num===1)returncount;constnextNum=num%2===0?num/2:3*num+1;returncollatzCount(nextNum,idx,arr,count+1);});console.log(collatzCountList);ジェネレーター式を使用してもかまいません。ただし、同じくthisに対する注意事項は理解した上で、という条件が付きます。
constprintGenerator=(g)=>{for(constvofg()){console.log(v);}};printGenerator(function*(){yield'こんにちは';yield'世界!';})
コールバックにメソッド
コールバックにメソッドをそのまま使用してはいけません。アロー関数で囲ってください。
classCalculator{constructor(number){this.number=number;}add(n){returnn+this.number;}allAdd(arr){// 呼び出し先の関数でのthisがundefinedになり、エラーreturnarr.map(this.add);}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);classCalculator{constructor(number){this.number=number;}add(n){returnn+this.number;}allAdd(arr){returnarr.map(n=>this.add(n));}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);または、bind()を用いて束縛するか、thisを明示的に指定してください。
classCalculator{constructor(number){this.number=number;}add(n){returnn+this.number;}allAdd(arr){returnarr.map(this.add.bind(this));}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);classCalculator{constructor(number){this.number=number;}add(n){returnn+this.number;}allAdd(arr){returnarr.map(this.add,this);}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);constructor()で、メソッドに対してbind()を用いてあらかじめthisに束縛することについては良いか悪いかは保留します。意見募集中。2
classCalculator{constructor(number){this.number=number;// addの呼び出しは常にthisに束縛されるようになるthis.add=this.add.bind(this);}add(n){returnn+this.number;}allAdd(arr){returnarr.map(this.add);}}constcalc=newCalculator(2);constlist=[2,3,5,7,11];constaddedList=calc.allAdd(list);console.log(addedList);
arguments
argumentsを使用してはいけません。デフォルト値、可変長引数を使用してください。
constf=function(x){vary=arguments[1];if(y==null){y=0;}varargs=3<=arguments.length?[].slice.call(arguments,2):[];returnconsole.log(x,y,args);};f(0,1,2,3);constf=(x,y=0,...args)=>{console.log(x,y,args);};f(0,1,2,3);
for...in
for...inを使用してはいけません。配列の反復などにはfor...of、map()、reduce()等を使用してください。Objectの場合はObject.keys()を使用してください。
constobj=Object.create({x:42});obj.a=2;obj.b=3;obj.c=5;for(constkeyinobj){// hasOwnPropertyでチェックしないとxも見てしまうif(!obj.hasOwnProperty(key))continue;constvalue=obj[key];console.log(`${key}:${value}`);}constobj=Object.create({x:42});obj.a=2;obj.b=3;obj.c=5;for(constkeyofObject.keys(obj)){constvalue=obj[key];console.log(`${key}:${value}`);}ECMAScript2017以降が使用できる場合は、Object.entries()やObject.values()を使用することもできます。
constobj=Object.create({x:42});obj.a=2;obj.b=3;obj.c=5;for(const[key,value]ofObject.entries(obj)){console.log(`${key}:${value}`);}
配列反復にfor(;;)
配列反復にfor(;;)を使用してはいけません。for...of、map、reduce等を使用してください。
constarr=[2,3,5,7,11];for(leti=0,len=arr.length;i<len;i++){console.log(arr[i]);}constarr=[2,3,5,7,11];for(constxofarr){console.log(x);}
forEach
forEachを使用してはいけません。for...ofを使用してください。また、可能な限り、mapやreduce等が使用できないかを検討してください。
constarr=[2,3,5,7,11];arr.forEach(x=>{console.log(x);});letsum=0;arr.forEach(x=>{sum+=x;});console.log(sum);constarr=[2,3,5,7,11];for(constxofarr){console.log(x);}constsum=arr.reduce((acc,x)=>acc+x,0);console.log(sum);
プロトタイプ作成に関数定義
プロトタイプを作成するために関数定義を使用してはいけません。クラス定義を使用してください。
constPerson=function(name,age){this.name=name;this.age=age;};Person.prototype.isAdult=function(){if(this.age>=20){returntrue;}else{returnfalse;}};consttaro=newPerson('Taro',18);console.log(taro.isAdult());classPerson{constructor(name,age){this.name=name;this.age=age;}isAdult(){if(this.age>=20){returntrue;}else{returnfalse;}}}consttaro=newPerson('Taro',18);console.log(taro.isAdult());
undefined (保証できないとき)
undefinedがundefined値であることを保証できない限り、undefinedを使用してはいけません。確実にundefined値であることを保証するときはvoid 0を使用してください。単純にundefined値を返す場合はreturn;を使用する、undefined値であることを確認する場合はtypeofを用いて'undefined'と比較してください。存在チェック(nullまたはundefinedではない)はx != nullで十分です。
constundefined=0;constf=()=>{returnundefined;}constx=0;consty=undefined;constz=f();console.log(x,x===undefined,x!=null);console.log(y,y===undefined,y!=null);console.log(z,z===undefined,z!=null);constundefined=0;constf=()=>{return;}constx=0;consty=void0;constz=f();console.log(x,typeofx==='undefined',x!=null);console.log(y,typeofy==='undefined',y!=null);console.log(z,typeofz==='undefined',z!=null);
Infinity、NaN (保証できないとき)
InfinityやNaNが無限や非数であることを保証できない限り、InfinityとNaNを使用してはいけません。確実に∞値や非数値であることを保証するときは1/0や0/0など計算結果を用いてください。
constInfinity=1;constNaN=0;console.log(Infinity);console.log(NaN);constInfinity=1;constNaN=0;console.log(1/0);console.log(0/0);
NaN (比較)
NaN(非数)のチェックに(たとえ、NaNが非数値であると保証されていても)NaNを使用してはいけません。代わりにisNaN()を使用してください。3
constx=0/0;// xはNaNなのにfalseになるconsole.log(x===NaN);constx=0/0;console.log(isNaN(x));
delete
deleteを使用してはいけません。Arrayはshift()、splice()、pop()を使用してください。連想配列はMapを使用してください。レコードはプロパティを削除しないでください。
constarr=[2,3,5,7,11];deletearr[arr.length-1];constdic={'林檎':'赤色','蜜柑':'黄色','桃':'桃色'};deletedic['林檎'];constapple={name:'林檎',color:'赤色',sugar:15};deleteapple.color;console.log(arr);console.log(dic);console.log(apple);constarr=[2,3,5,7,11];arr.pop();constdic=newMap([['林檎','赤色'],['蜜柑','黄色'],['桃','桃色']]);dic.delete('林檎');constapple={name:'林檎',color:'赤色',sugar:15};apple.color=null;console.log(arr);console.log(dic);console.log(apple);
厳格モードで削除される機能
厳格モードでは削除される機能(with文、暗黙のグローバル変数、8進数表記等)を使用してはいけません。なお、クラスやモジュールでは常に厳格モードになります。クラスやモジュールとして作成する場合は、'use strict';は書かないようにしてください。
with(Math){TAU=PI*02;}console.log(global.TAU);'use strict';global.TAU=Math.PI*2;console.log(golbal.TAU);
暗黙のセミコロン;
文末のセミコロン;を省略してはいけません。暗黙のセミコロン;を期待してはいけません。
constx=1console.log(x)constx=1;console.log(x);
{の前での改行
ブロックやObjectリテラルの開始である{の前で改行してはいけません。決してオールマンスタイルを採用してはいけません。字下げスタイルはJavaスタイルを採用してください。
classPerson{constructor(name,age){this.name=name;this.age=age;}isAdult(){if(this.age>=20){returntrue;}else{returnfalse;}}nameInfo(){// 構文エラーreturn{name:this.name,length:this.name.length};}}consttaro=newPerson('Taro',18);console.log(taro.isAdult());console.log(taro.nameInfo());classPerson{constructor(name,age){this.name=name;this.age=age;}isAdult(){if(this.age>=20){returntrue;}else{returnfalse;}}nameInfo(){return{name:this.name,length:this.name.length};}}consttaro=newPerson('Taro',18);console.log(taro.isAdult());console.log(taro.nameInfo());
returnのみの行
returnのみの行を作成してはいけません。undefined値を返したい場合はreturn;としてください。次の行が続くのであれば、()で括ってください。
constf=(x)=>{consti=2;// undefinedが返るreturnx*i;}console.log(f(3));constf=(x)=>{consti=2;return(x*i);}console.log(f(3));
即時関数で囲む
名前空間保護のために即時関数で囲む方法を使用してはいけません。代わりにモジュールベースで作成してください。
(function(globalObj){functionhello(){console.log('hello');}globalObj.hello=hello;})(this);exportfunctionhello(){console.log('hello');}
UTF-8以外のエンコード
エンコードはUTF-8を使用し、それ以外は使用しないでください。
ES5以前のJavaScript
ES6未対応ブラウザ(IE等)のために、ES5以前のJavaScript直接記述してはいけません。ECMAScript 2016以降(Babelでの変換が前提)を用いるか、TypeScript、CoffeeScript、LiveScript、PureScript、Opal等のAltJSで作成してください。4
Underscore
Underscoreを使用してはいけません。ほとんどの場合は不要です。もし、どうしても必要になる場合はLodashを使用してください。
jQueryによるDOM操作
jQueryでDOM操作をしてはいけません。JavaScriptのみでjQueryと同様のDOM操作は可能です。複雑なDOM操作を行いたい場合はReactやAngularJS等を検討してください。
IE対応
IEは捨ててください。考えるだけ無駄です。
推奨編

const
可能な限り変数はconstを付けて定数にしてください。変更する必要がある場合のみletを使用してください。

importexport
CommonJSであってもrequire()ではなくimportとexportの構文を使用してください。BabelやTypeScriptを正しく設定すれば、自動的にCommonJSやAMDの形式に変換してくれます。
アロー関数
関数式を使用しなければならない理由が無ければ、アロー関数を使用してください。一つの式のみでその結果を返す場合は、より簡潔に書くことができます。
Airbnb JavaScript Style Guide
スタイルガイドはAirbnb JavaScript Style Guide(以下Airbnb)を使用してください。この資料のほとんどの項目はこのスタイルガイドと同じになっています。
日本語訳もありますが、内容が古くなっています。Airbnbは、より良いものを模索しているため、常に更新され続けています。最新情報はgithub上のレポジトリを確認してください。
補足
このガイドにはなぜそうするのかの理由は書いてません。理由がどうしても知りたいという方は、@ms2satoさんが書いてくれた素晴らしい補足『「JavaScript初級者のためのコーディングガイド」に補足を試みる』をお読みください5。ただし、補足を読む前に、一度自分で理由を考えてください。他人の言葉ではなく自分の言葉で説明できて初めて意味があります。それができないうちは使用禁止です!
真にJavaScriptを学ぼうとする人の事です。使おうとする人のことではありません。↩
この書き方はReactのマニュアルHandling Eventsで紹介されている方法です。↩
JavaScriptの数値はIEEE 754で64bit binary(倍精度浮動小数点数)です。この浮動小数点数には数では無い(非数)ことを表すNaNが用意されています。通常、ほとんどの実装において、NaNは何と同じかどうかの比較をしても(NaN自身と比較をしても)必ず偽になります。↩
ECMAScript 2016とTypeScriptについては、このコーディングガイドの通りでしょう。しかし、他のaltJSはそのままでは採用できない物もあります。それらは、それらの流儀にしたがってください。↩
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme