web-dev-qa-db-ja.com

このキーワードを使用し、モジュールパターンを明らかにする厳格な違反

Jslint/jshintを渡すために次のものを取得するのに問題がある

/*jshint strict: true */
var myModule = (function() {
    "use strict";

    var privVar = true,
        pubVar = false;

    function privFn() {
        return this.test; // -> Strict violation.
    }

    function pubFn() {
        this.test = 'public'; // -> Strict violation.
        privFn.call(this); // -> Strict violation.
    }

    return {
        pubVar: pubVar,
        pubFn: pubFn
    };

}());

myModule.pubFn();

関数宣言でのthisの使用が原因であると理解していますが、Crockfordが書いたものを読んで、違反はグローバル変数の汚染を防ぐことを意図していると言いましたが、ここで唯一のグローバル変数は私ですm明示的に定義しています... myModule。他のすべては即時関数スコープに保持され、thisを使用してモジュールを参照できるはずです。

このパターンをどのように渡すことができますか?

更新:宣言の代わりに関数式を使用する場合、これは機能するようです。つまり、

var pubFn = function () { ...

私はこの形式のファンではありませんが、関数名と名前の付いたparamsを近づけて、宣言の見た目や雰囲気をよりクリーンにすることを好みます。正直なところ、なぜこれが違反を投げているのかわかりません-このパターンには理由がありません。

53
Matty F

JSHintには、validthisと呼ばれる option があります。

[...]は、コードがストリクトモードで実行され、非コンストラクター関数でthisを使用しているときに、ストリクトモードでthisの使用が有効であると確信している場合に、起こりうるストリクト違反に関する警告を抑制します。

JSHintが不平を言っている関数で使用します。あなたの場合、これは次のようになります。

function privFn() {
    /*jshint validthis: true */
    return this.test; // -> No Strict violation!
}

function pubFn() {
    /*jshint validthis: true */
    this.test = 'public'; // -> No Strict violation!
    privFn.call(this); // -> No Strict violation!
}

それを適用する各関数でそれを指定しなければならないのは苦痛に思えるかもしれませんが、モジュール関数の上部でオプションを設定する場合、genuine自分からの厳格なモード違反。

80
markrian

ここでの本当の問題は、モジュールコンテキスト内からprivFnを呼び出すと[ 〜#〜] iife [〜#〜])、厳格モードの場合、thisundefinedになります。厳密モードでない場合は、window。残念ながら、IIFE内から呼び出された場合、関数は失敗します。

これは、IIFE内から呼び出された場合、関数にowner(オブジェクト)がないため、返されたモジュールオブジェクトは、IIFEコンテキストの外部から呼び出された場合の関数の所有者です。たとえば、 _this === myModule_ myModule.pubFn()を呼び出すとき。

ストリクトモードとJSHint/JSLintの両方があなたを助けようとしているので、それらによって生成されたエラー/警告を無視するべきではなく、代わりにそれらが警告している理由を見つけてください。

privFnpubFnなどがモジュールの外部以外では呼び出されないことを100%確信している場合は、警告を生成する関数にコメント_/*jshint validthis: true */_を入れるだけです。 。または、IIFEの1つのコメントにより、モジュール内の関数でJSHintがこのエラーを生成することを防ぎます。


多くの可能な解決策の1つ

thisのスコープ(この例ではself内)を保存して、モジュールを明示的に参照します。これにより、意図が示され、確実になります。

_/*jshint strict: true */
var myModule = (function() {
    "use strict";

    var privVar = true,
        pubVar = false,
        self = this;

    function privFn() {
        return self.test;
    }

    function pubFn() {
        self.test = 'public';
        //privFn.call(this); // Will have no effect, as `privFn` does not reference `this`
        privFn();
    }

    return {
        pubVar: pubVar,
        pubFn: pubFn
    };
}());

myModule.pubFn();
_

残念ながら、これはこのセットアップの意図したエラーです。jslint/ jshintは、グローバルコンテキストで宣言された関数がオブジェクトメソッドとして後で使用されることを知らないためです。

4
Matty F