Строгое нарушение с использованием этого ключевого слова и раскрытие шаблона модуля
Не удалось получить следующее: 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 генерировать эту ошибку для любой функции внутри модуля.
Одно из многих возможных решений
Сохраните область 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();
Ответ 3
К сожалению, это предполагаемая ошибка для этой установки, поскольку jslint/jshint не знает, что функция, объявленная в глобальном контексте, должна быть позже использована как объектный метод.