JSHint Options 日本語訳

  • 89
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

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) camelCaseUPPER_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.callerarguments.calleeを禁止する。

変態チックで実は個人的に好きだが、プロダクトのコードで使うのはアレだ。恐らくトリッキーさゆえに、そもそもECMAScript 5で禁じられた (なのでStrict Modeでは使えない)。

noempty

空のブロックがあると警告を発する。

nonew

コンストラクタ関数をnewで呼び出した値を変数に格納することを強制する。

new MyConstructor();

この呼び出しで生成されたオブジェクトを再利用しないのであれば、newの利点を享受できないため。

plusplus

++--の使用を禁止する。

これらの演算子がコードクオリティを下げるという主張もあるため (Python文化圏とか) 。

(The Good Partsでも言及されていた気がしたが忘れた。本を貸したままなので内容確認できず。知っている方がいらしたらコメント頂けると幸いです)

quotmark

クオーテーションマークの一貫性を強制する。

truesingledoubleのいずれかを指定する。

  • 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

比較に===ではなく==を使っても警告を出さなくなる。

==による比較はnullundefinedのチェックが楽なので(両者がよくも悪くも厳密にチェックされなくなる)

esnext

ECMAScript 6独自のシンタックスの使用にお許しが出る。

ここでお許しが出る機能はまだ固まってないし、未対応ブラウザもあるので覚悟して使いましょう。

ECMAScript 6について詳しくは以下を参照

Draft Specification for ES.next (ECMA-262 Ed. 6)

evil

evalを利用しても警告が出なくなる。

これをevalevilと呼ぶこのセンス。

インジェクションの危険に晒される上、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

iffor等のブロック内で宣言した変数を、ブロックの外に出てから使った場合の警告を出ないようにする。

JavaScriptはのスコープは、グローバルスコープと関数スコープしかないのだが、if等のブロックがスコープを作っちゃうような気がして紛らわしいので、デフォルトではこの警告が出るようになっている。

function test() {
  if (true) {
    var x = 0;
  }

  // デフォルトでは x はスコープ外と判定されるが
  // このオプションを設定しているとここで警告が出ない
  x += 1;
}

globalstrict

グローバルスコープにuse strictすることを強いる。

グローバルスコープでこれをやるとサードパーティ製のコードが動かなくなるので、オススメしない。

strictオプションの記述も参照。

iterator

__iterator__プロパティを使った場合に警告が出ないようにする。

このプロパティはサポートされていないブラウザがあるから気を付けてね。

番外編: __iterator__プロパティとは

知らなかったので調べてみた。

https://developer.mozilla.org/ja/docs/Web/JavaScript/New_in_JavaScript/1.7

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