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

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

Есть идеи, как я могу передать этот шаблон?

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

var pubFn = function () { ...

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

Ответы [ 3 ]

79 голосов
/ 11 сентября 2012

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!
}

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

25 голосов
/ 29 января 2014

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

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

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

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


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

Сохраните область действия 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();
4 голосов
/ 24 июня 2011

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

...