Строгое нарушение с использованием этого ключевого слова и раскрытие шаблона модуля

Не удалось получить следующее: 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 в объявлении функции, но я прочитал что-то, что написал Крокфорд, и он сказал, что нарушение предназначено для предотвращения глобального переменного загрязнения - но единственной глобальной переменной здесь является то, m явно определяет... myModule. Все остальное хранится в области непосредственных функций, и я должен иметь возможность использовать this для ссылки на модуль.

Любые идеи, как я могу получить этот шаблон?

Обновление:, если я использую выражение функции вместо объявления, это работает, т.е.

var pubFn = function () { ...

Я не поклонник этого формата, но предпочитаю, чтобы имя функции и имена параметров были ближе, и декларация выглядит/чувствует себя чище. Я честно не понимаю, почему это бросает нарушение - нет причин для этого в этом шаблоне.

Ответ 1

JSHint имеет вариант под названием validthis, который:

[...] подавляет предупреждения о возможных строгих нарушениях, когда код работает в строгом режиме, и вы используете 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!
}

Может показаться, что боль должна указывать, что в каждой функции, где она применяется, но если вы установите опцию в верхней части своей функции модуля, вы можете скрывать от себя неподдельные нарушения строгого режима.

Ответ 2

Реальная проблема заключается в том, что если вы вызываете privFn из контекста модуля (из IIFE), this будет undefined в строгом режиме; window если не в строгом режиме. Увы, функция не сработает, если вызвана из IIFE.

Это связано с тем, что функции не имеют владельца (объект) при вызове из IIFE, тогда как возвращаемый объект модуля является владельцем функций при их вызове со стороны контекста IIFE, например this === myModule при вызове myModule.pubFn().

Как строгий режим, так и JSHint/JSLint пытаются вам помочь, и вы никогда не должны просто игнорировать ошибки/предупреждения, созданные ими, но вместо этого выяснить, почему они предупреждают вас.

Если вы на 100% уверены, что privFn, pubFn и т.д. не будут вызываться нигде, кроме внешнего модуля, просто добавьте комментарий /*jshint validthis: true */ в любые функции, генерирующие предупреждение. В качестве альтернативы, один комментарий в IIFE не позволит JSHint генерировать эту ошибку для любой функции внутри модуля.


Одно из многих возможных решений

Сохраните область thisself в этом примере), чтобы явно ссылаться на модуль. Это покажет и обеспечит ваши намерения.

/*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();

Ответ 3

К сожалению, это предполагаемая ошибка для этой установки, поскольку jslint/jshint не знает, что функция, объявленная в глобальном контексте, должна быть позже использована как объектный метод.