読者です 読者をやめる 読者になる 読者になる

ぶれすとつーる

だいたいjavascript

JSLint will hurt your feelings.

JSLint:Douglas Crockford氏作JSの品質向上ツール


もうけちょんけちょんにエラーで指摘されるのは慣れてきたので、僕がふるぼっこにされながら学んだJSLint様に指摘されない書き方を紹介する。

実際に自分のコードに非のある場合のエラーは一目瞭然なので、知らんと分からん!てものとかについて紹介

今回はオプション無しバージョンでのチェックを前提とします。

Move the invocation into the parens that contain the function.

(function () {
    alert('hogehoge'); 
})();

即時関数をこんな感じで書いてるときにでる警告。

即時関数とはもともとピュアな形は以下の書き方をするもの
(アンチパターン)

function () {
    alert('hogehoge'); 
}();

でもそれだと末尾の()を見落としちゃうことがあるってことで全体を以下のようにラップする形が好まれている

(function () {
    alert('hogehoge'); 
}());

こういう経緯でこの書き方になっているのでこの書き方を支持しましょう。ってことだと思います。
ただ、冒頭の(function () {})();もアンチパターンというわけではなく()の見落としもないであろう書き方なのでJSLintには指摘されるものの問題のある構文ではありません。

現にDouglas氏もGood Partsの中でそれ使ってたし。

Implied global: .....

(function (doc) {
    var hoge = doc.getElementById('foo');
    hoge.innerHTML = "fugafuga";
}(document));

Error: Implied global: document 4


JSLintはひたすらグローバル変数を指摘してくれます。
ただ、グローバルを一切使わずに書くのは不可能で、documentとかsetIntervalとか作るものにとっては必須のものまで指摘されるのは。。。ってなっちゃいますよね。

これはグローバルを指摘しているというよりは、「暗黙のうちに使ってしまっているグローバル」を指摘しています。

なので、これはグローバルだけど分かって使ってるもんって作者が理解していれば問題のないことで、それをコメントを使ってLintにも知らせてやればいいのです。

/*global document */
(function (doc) {
    var hoge = doc.getElementById('foo');
    hoge.innerHTML = "fugafuga";
}(document));

'hoge' was used before it was defined.

/*global alert */
(function () {
    hoge();

    function hoge() {
        alert("foo");
    }
}());

Error:
Problem at line 5 character 18: 'hoge' was used before it was defined.

function hoge() {

Implied global: hoge 3

Unused variable: hoge 2 "anonymous"


上記ソースはこんな感じで指摘してくれると思います。

まず、hogeは定義されてない。 hogeはグローバルだ。 hogeは使われていない。

そんな、ばかな。

明らかに定義されているし、ローカルスコープだし、使われている。

これはおそらくJSLintのパース順序が上から下だということに基づくエラーと思われる。

通常、コンパイル時にfunction hoge() {} は準備状態になるが、Lintのように上から順にパースされる場合、hoge()を実行してる段階でhoge関数はそれより下で定義されてるので、Lintはこのスコープ内でまだ定義されてない関数を呼んだと理解し、グローバルを参照したといって警告するわけです。

さらにパースがhoge関数の定義に差し掛かると、今度はこれが定義されてから一度も参照されてないといって指摘するわけです。

なのでLintにも分かるよう、以下のように書くことでこのエラーは回避できます。

/*global alert */
(function () {
    function hoge() {
        alert("foo");
    }

    hoge();
}());

ほかにもいろいろ細かいのがあると思いますが、過去結構はまったものだけ載せておきました。
また思い出したらいろいろ書きます。