JSHintの設定を色々いじってみようとおもったので、
原文 http://www.jshint.com/docs/options/ を非常に雑に意訳。
主観を交えながら書いていたら、どこまでがJSHintのドキュメントでどこからが主観なのか判別のし難い悪文になっている。
http://www.jshint.com/docs/ の内容も若干含む。
JavaScriptの注意事項一覧として見てもよい内容だと思う(原文が)。
これらを有効にする方法は以下の3通りの様子。
- jshintコマンドのオプションとして指定
- jsファイルの先頭にコメント挿入
- .jshintrcに設定を記述
Enforcing options
これらにtrue
を設定することで、JSHintはより厳しく警告を出すようになる。
bitwise
ビット演算子^
、|
等を禁ずる。
JavaScriptにおいてビット演算子が必要になることは稀なので、&
は&&
のタイポだったりする。
camelcase
変数名をキャメルケース、または大文字のアンダースコア区切りのみとする。
(ex) camelCase
、UPPER_CASE
curly
ループや条件分岐のブロックをブレイス{}
で囲うことを強制する。
JavaScriptでは、以下のような1ステートメントのみの場合のみブレイスの省略が可能である。
while (day)
shuffle();
しかし以下のようにブロック内に入っているんだかいないんだか分からない記述がバグの元になる。
while (day)
shuffle();
sleep();
eqeqeq
==
、!=
を禁止して===
、!==
を強制する。
前者の等価演算子は、予期せぬ振る舞いをするため。
es3
ECMAScript 3の仕様に乗っ取ることを強いられる。
旧IE等のレガシーな環境対策用。
forin
for-inループでオブジェクトのプロパティの探査をする際、hasOwnProperty
によるプロパティのチェックを強制する。
for-inループでは予期せぬプロパティが含まれる場合があるため。詳細は「Exploring JavaScript for-in loops / Angus Croll」を参照。
for (key in obj) {
if (obj.hasOwnProperty(key)) {
// obj[key] が obj のものであってプロトタイプ継承元のものでないことを保証できる
}
}
freeze
Array
等ネイティブオブジェクトのプロトタイプの変更を禁止する。
/* jshint freeze:true */
Array.prototype.count = function (value) { return 4; };
// ネイティブオブジェクトであるArrayのprototypeを拡張したらアカン
immed
パーレン()
で囲わない即時関数を禁止する。
コードを読む際、関数ではなく関数の実行結果であることが明示されるため。
indent
インデント幅を強制する。以下の例ではスペース4つでないと警告が出る。
/*jshint indent:4 */
if (cond) {
doSomething(); // インデントおかしい
}
latedef
変数を定義前に使うことを禁止する。
JavaScriptは関数スコープであり、ホイスティングによって変数は関数トップで宣言されたことになるため、これがバグの元になり得る。
安全にコードを書くためには (C言語的に) 関数のトップで明示的に宣言するべきである。
このオプションをnofunc
にすると、関数宣言は警告の対象に含めないようになる。
↑ここがちょっと分からなかった。
関数宣言function hoge(){}
と、関数定義var f = function(){};
の2つがあり、
前者はトリッキーな動きをするのだが、この前者で警告は出さないよってこと?
原文: Setting this option to "nofunc" will allow function declarations to be ignored.
JavaScriptのスコープとホイスティングを理解するには「JavaScript Scoping and Hoisting / Ben Cherry」を読むべし。
newcap
コンストラクタ関数の名前は大文字で始めることを強制する。
これにより、new演算子で呼び出す関数であることを明示する。
コンストラクタ関数をnewなしで呼び出すと、呼び出し自体はできて、this
がグローバルオブジェクトを指してバグが起きるため。
noarg
arguments.caller
、arguments.callee
を禁止する。
変態チックで実は個人的に好きだが、プロダクトのコードで使うのはアレだ。恐らくトリッキーさゆえに、そもそもECMAScript 5で禁じられた (なのでStrict Modeでは使えない)。
noempty
空のブロックがあると警告を発する。
nonew
コンストラクタ関数をnewで呼び出した値を変数に格納することを強制する。
new MyConstructor();
この呼び出しで生成されたオブジェクトを再利用しないのであれば、newの利点を享受できないため。
plusplus
++
、--
の使用を禁止する。
これらの演算子がコードクオリティを下げるという主張もあるため (Python文化圏とか) 。
(The Good Partsでも言及されていた気がしたが忘れた。本を貸したままなので内容確認できず。知っている方がいらしたらコメント頂けると幸いです)
quotmark
クオーテーションマークの一貫性を強制する。
true
、single
、double
のいずれかを指定する。
- true: シングルクオーテーションでもダブルクオーテーションでもいいがどちらかに統一することを強制
- single: シングルクオーテーションを強制
- double: ダブルクオーテーションを強制
undef
var
宣言されていない変数を使用することを禁止する。
変数のタイポだったり、うっかりvar
忘れの検知に便利(var忘れはglobal変数へのアクセスになって危険)。
This option prohibits the use of explicitly undeclared variables. This option is very useful for spotting leaking and mistyped variables.
/*jshint undef:true */
function test() {
var myVar = 'Hello, World';
console.log(myvar); // ここのタイポを警告してくれる
}
別ファイルで宣言している変数を利用したい場合、/*global ... */
によってJSHintに宣言してない変数だけど怒らないでね、と伝えることができる。
/*global hoge */
console.log(hoge); // 宣言していない変数hogeを使ってもOK
unused
宣言しても使っていない変数があったら警告する。
未使用コードの掃除に便利。
/*jshint unused:true */
function test(a, b) {
var c, d = 2;
return a + d;
}
test(1, 2);
// Line 3: 'b' was defined but never used.
// Line 4: 'c' was defined but never used.
加えてこのオプションは、/*global ... */
で宣言しているが使っていないグローバル変数も警告してくれる。
このオプションにvars
を設定すると、関数の引数はチェックせず変数のみをチェックする。strict
を設定すると全ての変数をチェックする。デフォルト値(true)は、使われているパラメータの次の使われていないパラメータについて、許可する。
strict
全ての関数に対して、ECMAScript 5のstrict modeを求めるようになる。
strict modeは、標準でないJavaScriptを禁止する。
やばいんだけどエラーにはならない記述があった場合に、エラーを発するようになる。
加えてJavaScriptエンジンが最適化をしにくくなる記述も修正できる。
※このオプションはstrict modeを関数スコープにのみ強いる。グローバルスコープには強制しない。グローバルスコープに強制してしまうと、サードパーティ製のものがエラーを吐く可能性があるからだ。もしグローバルスコープのstrict modeを強制したい場合はglobalstrict
オプションを用いること。
trailing
行末のホワイトスペースを許さない。
複数行の文字列があったりすると、事故が起きるので。
// バックスラッシュの後にホワイトスペースがあったら
// エラーになる
var str = "Hello \
World";
maxparams
関数に指定できる引数の数を制限する。
/*jshint maxparams:3 */
function login(request, onSuccess) {
// ...
}
// JSHint: Too many parameters per function (4).
// 引数は3つまでって言ったでしょ!
function logout(request, isManual, whereAmI, onSuccess) {
// ...
}
maxdepth
ブロックのネスト数を制限する。
/*jshint maxdepth:2 */
function main(meaning) {
var day = true;
if (meaning === 42) {
while (day) {
shuffle();
if (tired) {
// JSHint: Blocks are nested too deeply (3).
// ネストは2段までって言ったでしょ!
sleep();
}
}
}
}
maxstatements
1つの関数に含められるステートメントの数を制限する。
/*jshint maxstatements:4 */
function main() {
var i = 0;
var j = 0;
// 関数の宣言は1ステートメントとしてカウントする
function inner() {
var i2 = 1;
var j2 = 1;
return i2 + j2;
}
j = i + j;
// JSHint: Too many statements per function. (5)
// ステートメントは4つまでって言ったでしょ!
return j;
}
maxcomplexity
循環的複雑度(cyclomatic complexity)を制限する。
循環的複雑度っていうのはコードの複雑さの指標で、詳しくはWikipedia参照。
※あまり分かってないですが、条件分岐(ループ含む)によってコードには様々な経路が発生するわけで、その経路の数をカウントしているような感じ、なのかな?
maxlen
1行あたりの最大文字数を制限する。
Relaxing options
true
をセットした項目について、JSHintが警告を出さなくなる。
割と危険な香りがするので、さらに雑に訳して行く。
asi
セミコロンなしの警告を出さなくなる。
以下、原文まま(エネルギーが尽きました。ごめんなさい)。
There is a lot of FUD about semicolon spread by quite a few people in the community. The common myths are that semicolons are required all the time (they are not) and that they are unreliable. JavaScript has rules about semicolons which are followed by all browsers so it is up to you to decide whether you should or should not use semicolons in your code.
For more information about semicolons in JavaScript read An Open Letter to JavaScript Leaders Regarding Semicolons by Isaac Schlueter and JavaScript Semicolon Insertion.
boss
条件式を入れる場所で変数への代入をしていても警告を出さなくなる。
たとえばif (a = 10) {}
はタイポなわけだが、便利なケースもあるので。
for (var i = 0, person; person = people[i]; i++) {}
上記は()
で囲うことでJSHintを黙らせることができる。
for (var i = 0, person; (person = people[i]); i++) {}
Ruby文化だとショートに書くのが好まれて、こうした書き方は割とあるかな?
C言語系は、逆に==
のタイポと紛らわしいので嫌われる印象。
debug
debugger宣言していても警告を出さなくなる。
eqnull
比較に===
ではなく==
を使っても警告を出さなくなる。
==
による比較はnull
、undefined
のチェックが楽なので(両者がよくも悪くも厳密にチェックされなくなる)
esnext
ECMAScript 6独自のシンタックスの使用にお許しが出る。
ここでお許しが出る機能はまだ固まってないし、未対応ブラウザもあるので覚悟して使いましょう。
ECMAScript 6について詳しくは以下を参照
Draft Specification for ES.next (ECMA-262 Ed. 6)
evil
eval
を利用しても警告が出なくなる。
これをeval
をevil
と呼ぶこのセンス。
インジェクションの危険に晒される上、JavaScriptインタプリタが最適化するのが困難になるので、激しくオススメしない。
expr
読んでも分からなかったので原文まま。
This option suppresses warnings about the use of expressions where normally you would expect to see assignments or function calls. Most of the time, such code is a typo. However, it is not forbidden by the spec and that's why this warning is optional.
funcscope
if
やfor
等のブロック内で宣言した変数を、ブロックの外に出てから使った場合の警告を出ないようにする。
JavaScriptはのスコープは、グローバルスコープと関数スコープしかないのだが、if
等のブロックがスコープを作っちゃうような気がして紛らわしいので、デフォルトではこの警告が出るようになっている。
function test() {
if (true) {
var x = 0;
}
// デフォルトでは x はスコープ外と判定されるが
// このオプションを設定しているとここで警告が出ない
x += 1;
}
globalstrict
グローバルスコープにuse strict
することを強いる。
グローバルスコープでこれをやるとサードパーティ製のコードが動かなくなるので、オススメしない。
strictオプションの記述も参照。
iterator
__iterator__
プロパティを使った場合に警告が出ないようにする。
このプロパティはサポートされていないブラウザがあるから気を付けてね。
番外編: __iterator__
プロパティとは
知らなかったので調べてみた。
JavaScript 1.7かい。ジェネレータ使いたいなあ。
hoge
っていうオブジェクトの中身をトラバースするのに使うイテレータを、hoge.__iterator__()
というメソッド呼び出しで返却するようにすることで指定できる。
イテレータの特性として求められるのは次の2点である。
-
next
関数のメソッド呼び出しで次の要素を取得できる - 次の要素が存在しない状態で
next
を呼ぶとStopIteration
例外を投げる
うろ覚えだけれどPythonもこんなんじゃなかたっけ?
これ以外にも、JavaScriptはPythonインスパイアされていってる印象だし。
lastsemic
セミコロン忘れの警告を出ないようにする。
※ただし1行のコードブロックの最後のステートメントに限る
var name = (function() { return 'Anton' }());
これは非常にニッチな需要だが、JavaScriptのコードを自動生成する場合には便利だ
…って、Google Closure Compiler辺りがコードボリューム削減のためにこういうコード吐いたりするっけ?で、Jenkinsとかでまとめてコードチェックかける場合に便利、とかそんな感じ?
laxbreak
安全でない改行があっても警告が出ないようにする。
安全でない改行って、妙な位置で改行してるパターンってことかな?
可読性が下がるとは思うけれど、危険になるのってどういうケースだろう?
なお、ファイル先頭にカンマを入れるコードディングスタイルの警告抑止については、後述のlaxcommaを参照してね。
laxcomma
カンマを行頭に持ってくるコードディングスタイルに文句を言わなくなる。
var obj = {
name: 'Anton'
, handle: 'valueof'
, role: 'SW Engineer'
};
loopfunc
ループ内での関数定義に文句を言わなくなる。
ループ内での関数定義はバグを誘発しやすい。
var nums = [];
for (var i = 0; i < 10; i++) {
nums[i] = function (j) {
return i + j;
};
}
nums[0](2); // ここで2が出ると見せかけて、12が出力される。
上記コードを正しくするには、以下のように書く必要がある。
var nums = [];
for (var i = 0; i < 10; i++) {
(function (i) {
nums[i] = function (j) {
return i + j;
};
}(i));
}
手前味噌ですが、以前のワタクシの投稿でも上記手法に言及しています。
http://qiita.com/xorphitus/items/40aa10d093e8b7fa0699#2-11
moz
MozillaのJavaScript拡張を利用しているよー、とJSHintに教えてあげる。
Firefoxに特化した開発をしているわけでないのなら、このオプションは必要ないっす。
詳細:
New in JavaScript 1.7
multistr
複数行の文字列に警告を出さなくなる。
複数行の文字列は、エスケープ文字\
と次の行の先頭との間にホワイトスペースが入ると、マジ事故って危ない。
それでも正しく複数行の文字列を使うから許しとくれよー、とこのオプションを有効にした勇者には、エスケープ文字の付近が妙なことになっていないかのチェックだけはやってくれるという優しさを見せる。
/*jshint multistr:true */
var text = "こんにちは\
世界"; // これは大丈夫
text = "こんにちは
世界"; // エスケープ文字がないので警告
text = "こんにちは\
世界"; // エスケープ文字の後にスペースが入っているので警告
notypeof
typeof
演算子と比較する値がアレだった場合でも警告を出さなくなる。
この演算子が返す値はごく限られているので、JSHintはデフォルトでは以下のコードはタイポとみなして警告を発する。
// 'fuction' instead of 'function'
if (typeof a == "fuction") { // 'fuction' なんて型はねーよ
/* ... */
}
絶対の自信がない限り、このオプションを有効にするのはやめましょう。
ってか、完璧なコードが書けるつもりだったとしてもやめておきましょう、と思う。人間は間違いを犯すもの。
proto
__proto__
プロパティにアクセスしても警告をしなくなる。
__proto__
プロパティ
プロトタイプ継承した時に、実はprototype
プロパティじゃなくてこっちが使われている。
旧IEあたりでは使ってなかった気がするので、それでデフォルトでは警告を出すんじゃなかろうか。
var Fun = function () {};
Fun.prototype.hoge = 123;
var f = new Fun();
console.log(f.hoge); // 123が出力される
console.log(f.__proto__.hoge); // 123が出力される
余談になるが、アドレスで参照しているので2行目と3行目を入れ替えても大丈夫。というか、うっかり書き換えに注意。
var Fun = function () {};
var f = new Fun();
Fun.prototype.hoge = 123;
console.log(f.hoge); // やっぱり123が出力される
console.log(f.__proto__.hoge); // やっぱり123が出力される
scripturl
こんな感じの、スクリプト実行系のURLを生成した時に怒らなくなる。
var x = 'javascript: foo()';
smarttabs
タブとスペースが混在しても警告しなくなる。
このテクニックはSmartTabsと呼ばれる…うーん、なんだかなあ。
shadow
変数名のシャドーイングに文句を言わなくなる。
以下みたいなコードのことを言ってるのかと思ったけど、デフォルト設定でこれを書いても警告が出なかった…。何か勘違いしてるんだろうか。
var hoge = 1;
(function () {
var hoge = 2;
})();
sub
obj['name']
じゃなくてobj.name
って書けよ!という文句を言ってこなくなる。
supernew
"weird"コンストラクション、つまりは new function () { ... }
みたいなやつを受け入れてくれる。シングルトンで使うかも知れないしね。
var singleton = new function() {
var privateVar;
this.publicMethod = function () {}
this.publicMethod2 = function () {}
};
(publicのみのシングルトン的なことをしたいならオブジェクトリテラルでいいと思うし、上記の様にprivateを導入したいならクロージャ書いちゃった方が個人的にはすっきりするのだが)
validthis
何かよく分からなかったので、原文まま。
This option suppresses warnings about possible strict violations when the code is running in strict mode and you use this in a non-constructor function. You should use this option—in a function scope only—when you are positive that your use of this is valid in the strict mode (for example, if you call your function using Function.call).
※このオプションは関数スコープ内でのみ使える。グローバルにこのオプションを指定するとJSHintはエラーで失敗する
Environments
JSHintに元々用意されているグローバル変数を教えるためのオプションたち。
browser
navigator
とかHTML5 FileReaderのオブジェクトとか、今どきブラウザが用意しているオブジェクトがグローバル宣言されていることになる。
※console
とかalert
といったオブジェクトについてはdevel
の方を参照
couch
CoudhDBの用意しているオブジェクトがグローバル宣言されていることになる。
devel
console
とかalert
とか、デバッグに使うオブジェクトがグローバル宣言されていることになる。
プロダクションではこの設定を外した方がいい。console.log
と書いてあると、古いIEが爆発するエラーを吐くので。
dojo
Dojo Toolkitの用意しているオブジェクトがグローバル宣言されていることになる。
jquery
jQueryの用意しているオブジェクトがグローバル宣言されていることになる。
mootools
MooToolsの用意しているオブジェクトがグローバル宣言されていることになる。
node
Node.jsの用意しているオブジェクトがグローバル宣言されていることになる。
加えて、ブラウザ環境であれば警告とみなす記述に目をつぶってくれる。
ファイル毎のuse strict
宣言とか、console.log
とか。
(後者の具体的な中身は未調査です)
nonstandard
標準で用意されていないがよく使われるグローバル変数をグローバル宣言していることにする。
escape
とかunescape
とか。
(んー、個人的にこれは危険な香りがする…)
phantom
PhantomJSの用意しているオブジェクトがグローバル宣言されていることになる。
prototypejs
Protytype.jsの用意しているオブジェクトがグローバル宣言されていることになる。
rhino
Rhinoの用意しているオブジェクトがグローバル宣言されていることになる。
worker
Web Workerの用意しているオブジェクトがグローバル宣言されていることになる。
wsh
Windows Script Hostの用意しているオブジェクトがグローバル宣言されていることになる。
yui
YUIの用意しているオブジェクトがグローバル宣言されていることになる。
Legacy
これらのオプションは廃止対象であり、近いうちに削除されるので使わないように。
というわけで日本語訳は省略。
- nomen
- onevar
- passfail
- white