this
this
(иначе говоря, «контекст») - это специальное ключевое слово внутри каждой функции, и его значение зависит только от , как была вызвана функция, а не как / когда / где она была определена. Лексические области не затрагиваются, как и другие переменные. Вот несколько примеров:
function foo() {
console.log(this);
}
// normal function call
foo(); // `this` will refer to `window`
// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`
// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`
Чтобы узнать больше о this
, просмотрите документацию MDN .
this
this
Фактически вы не хотите иметь доступ к this
в частности, но объект, на который он ссылается на . Вот почему простое решение - просто создать новую переменную, которая также относится к этому объекту. Переменная может иметь любое имя, но общие - self
и that
.
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}
Поскольку self
является нормальной переменной, она подчиняется лексическим правилам области и доступна внутри обратного вызова. Это также имеет то преимущество, что вы можете получить доступ к значению this
самого обратного вызова.
this
обратного вызова - часть 1 Возможно, у вас есть не контролируйте значение this
, потому что его значение устанавливается автоматически, но на самом деле это не так.
Каждая функция имеет метод .bind
[docs] , который возвращает новую функцию с this
, привязанную к значению. Функция имеет то же поведение, что и тот, который вы назвали .bind
, только то, что this
было установлено вами. Независимо от того, как и когда эта функция вызывается, this
всегда будет ссылаться на переданное значение.
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}
В этом случае мы привязываем обратный вызов this
к значению MyConstructor
's this
.
Примечание. При связывании контекста для jQuery вместо этого используйте jQuery.proxy
[docs] . Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене обратного вызова события. jQuery обрабатывает это внутренне.
В ECMAScript 6 представлены функции стрелок , которые можно рассматривать как лямбда-функции. У них нет собственной привязки this
. Вместо этого this
просматривается в области видимости как обычная переменная. Это означает, что вам не нужно называть .bind
. Это не единственное особое поведение, которое у них есть. Дополнительную информацию см. В документации MDN.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
this
обратного вызова - часть 2 Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, к которому должен обращаться обратный вызов this
. Это в основном то же самое, что и привязывать его самостоятельно, но функция / метод делает это за вас. Array#map
[docs] - такой метод. Его подпись такова:
array.map(callback[, thisArg])
Первый аргумент - это обратный вызов, а второй аргумент - значение this
. Вот надуманный пример:
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
Примечание. Можно ли передать значение для this
, как правило, упоминается в документации этой функции / метода. Например, метод $.ajax
jQuery [docs] описывает параметр, называемый context
:
Этот объект станет контекстом всех обратных вызовов, связанных с Ajax.
Общая проблема: использование объектных методов в качестве обработчиков обратных вызовов / событий
Еще одно распространенное проявление этой проблемы - когда объектный метод используется как обработчик обратного вызова / события , Функции являются первоклассными гражданами в JavaScript, а термин «метод» - просто разговорный термин для функции, которая является значением свойства объекта. Но эта функция не имеет конкретной ссылки на ее «содержащий» объект.
Рассмотрим следующий пример:
function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); };
Функция
this.method
назначается как обработчик события click , но если щелкнутьdocument.body
, зарегистрированное значение будетundefined
, потому что внутри обработчика событияthis
ссылается наdocument.body
, а не на экземплярFoo
. Как уже упоминалось в начале, то, что относится к [49], зависит от того, как называется функция, а не от того, как она определена. Если код выглядит следующим образом, может быть более очевидно, что функция не имеет неявной ссылки на объект:function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method;
Решение такое же, как указано выше: если доступно, используйте
.bind
явно привязатьthis
к определенному значениюdocument.body.onclick = this.method.bind(this);
или явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обработчика обратного вызова / события и назначить object (
this
) к другой переменной:var self = this; document.body.onclick = function() { self.method(); };
или использовать функцию стрелки:
document.body.onclick = () => this.method();
Проверьте использование supressionCommentFilter в http://checkstyle.sourceforge.net/config_filters.html#SuppressionCommentFilter . Вам нужно будет добавить модуль в свой checkstyle.xml
<module name="SuppressionCommentFilter"/>
и его можно настроить. Таким образом, вы можете добавлять комментарии к своему коду, чтобы отключить контрольный стиль (на разных уровнях), а затем снова включить его с помощью комментариев в вашем коде. Например,
//CHECKSTYLE:OFF
public void someMethod(String arg1, String arg2, String arg3, String arg4) {
//CHECKSTYLE:ON
Или еще лучше используйте эту более измененную версию:
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="CHECKSTYLE.OFF\: ([\w\|]+)"/>
<property name="onCommentFormat" value="CHECKSTYLE.ON\: ([\w\|]+)"/>
<property name="checkFormat" value="$1"/>
</module>
, которая позволяет отключать специальные проверки для определенных строк кода:
//CHECKSTYLE.OFF: IllegalCatch - Much more readable than catching 7 exceptions
catch (Exception e)
//CHECKSTYLE.ON: IllegalCatch
* Примечание: вам также нужно будет добавить FileContentsHolder
:
<module name="FileContentsHolder"/>
См. также
<module name="SuppressionFilter">
<property name="file" value="docs/suppressions.xml"/>
</module>
в разделе SuppressionFilter на той же странице , который позволяет вам отключать отдельные проверки для сопоставленных шаблонов ресурсов.
Итак, если у вас есть в вашем checkstyle.xml:
<module name="ParameterNumber">
<property name="id" value="maxParameterNumber"/>
<property name="max" value="3"/>
<property name="tokens" value="METHOD_DEF"/>
</module>
Вы можете отключить его при подавлении xml-файл с помощью:
<suppress id="maxParameterNumber" files="YourCode.java"/>
Другой способ, доступный в Checkstyle 5.7, заключается в подавлении нарушений с помощью аннотации @SuppressWarnings
java. Для этого вам понадобится новые модули (SuppressWarningsFilter и SuppressWarningsHolder) в вашем файле конфигурации:
<module name="Checker">
...
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
...
<module name="SuppressWarningsHolder" />
</module>
</module>
Затем в коде вы можете сделать следующее:
@SuppressWarnings("checkstyle:methodlength")
public void someLongMethod() throws Exception {
или для множественных подавлений:
@SuppressWarnings({"checkstyle:executablestatementcount", "checkstyle:methodlength"})
public void someLongMethod() throws Exception {
Примечание: префикс «checkstyle:
» является необязательным (но рекомендуется). Согласно документам имя параметра должно быть во всех строчных строках, но практика показывает, что любой случай работает.
Если вы предпочитаете использовать аннотации для выборочного отключения правил, теперь это возможно, используя аннотацию @SuppressWarnings
, начиная с Checkstyle 5.7 (и поддерживаемая плагином Checkstyle Maven 2.12 +).
Сначала, в checkstyle.xml
добавьте модуль SuppressWarningsHolder
в TreeWalker
:
<module name="TreeWalker">
<!-- Make the @SuppressWarnings annotations available to Checkstyle -->
<module name="SuppressWarningsHolder" />
</module>
Затем включите SuppressWarningsFilter
там (в качестве брата с TreeWalker
):
<!-- Filter out Checkstyle warnings that have been suppressed with the @SuppressWarnings annotation -->
<module name="SuppressWarningsFilter" />
<module name="TreeWalker">
...
Теперь вы можете аннотировать, например метод, который вы хотите исключить из некоторого правила Checkstyle:
@SuppressWarnings("checkstyle:methodlength")
@Override
public boolean equals(Object obj) {
// very long auto-generated equals() method
}
Префикс checkstyle:
в аргументе @SuppressWarnings
является необязательным, но мне нравится это как напоминание о том, откуда это предупреждение. Имя правила должно быть строчным.
Наконец, если вы используете Eclipse, он будет жаловаться на неизвестный ему аргумент:
Unsupported @SuppressWarnings ("checkstyle : methodlength ")
blockquote>Вы можете отключить это предупреждение Eclipse в настройках, если хотите:
Preferences: Java --> Compiler --> Errors/Warnings --> Annotations --> Unhandled token in '@SuppressWarnings': set to 'Ignore'
В каждом ответе, относящемся к SuppressWarningsFilter , отсутствует важная деталь. Вы можете использовать только строчный идентификатор, если он определен как таковой в вашем файле checkstyle-config.xml. Если нет, вы должны использовать оригинальное имя модуля.
Например, если в моем checkstyle-config.xml у меня есть:
<module name="NoWhitespaceBefore"/>
Я не могу использовать:
@SuppressWarnings({"nowhitespacebefore"})
Я должен, use:
@SuppressWarnings({"NoWhitespaceBefore"})
Для того, чтобы первый синтаксис работал, checkstyle-config.xml должен иметь:
<module name="NoWhitespaceBefore">
<property name="id" value="nowhitespacebefore"/>
</module>
Это то, что сработало для меня, по крайней мере, в версия CheckStyle 6.17.
Что также хорошо работает, это SuppressWithNearbyCommentFilter , который использует отдельные комментарии для подавления событий аудита.
Например
// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
public void onClick(View view) { ... }
Чтобы настроить фильтр так, что CHECKSTYLE IGNORE проверяет СЛЕДУЮЩИЙ var LINES избегает запуска любых проверок для данной проверки для текущей строки и следующих строк var (всего для var + 1 строки):
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
<property name="checkFormat" value="$1"/>
<property name="influenceFormat" value="$2"/>
</module>
CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES?
, что сделает команду ignore более удобочитаемой. (Вы сможете использовать «CHECKSTYLE IGNORE check FOR NEXT 1 LINE» и «CHECKSTYLE IGNORE check FOR NEXT 3 LINES»).
– Matt3o12
28 May 2014 в 18:10
CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINE
также работает для меня (он соответствует как line
, так и lines
).
– Slava Semushin
22 July 2015 в 08:10
<module name="Checker">
<module name="SuppressionCommentFilter"/>
<module name="TreeWalker">
<module name="FileContentsHolder"/>
</module>
</module>
Чтобы настроить фильтр для подавления событий аудита между комментарием, содержащим строку BEGIN GENERATED CODE, и комментарий, содержащий строку END GENERATED CODE:
<module name="SuppressionCommentFilter">
<property name="offCommentFormat" value="BEGIN GENERATED CODE"/>
<property name="onCommentFormat" value="END GENERATED CODE"/>
</module>
//BEGIN GENERATED CODE
@Override
public boolean equals(Object obj) { ... } // No violation events will be reported
@Override
public int hashCode() { ... } // No violation events will be reported
//END GENERATED CODE
У меня возникли трудности с ответами выше, возможно, потому что я установил предупреждения checkStyle как ошибки. Что делало SuppressionFilter: http://checkstyle.sourceforge.net/config_filters.html#SuppressionFilter
Недостатком этого является то, что диапазон строк сохраняется в отдельных подавлениях .xml, поэтому незнакомый разработчик не может сразу установить соединение.
//CHECKSTYLE.OFF:
, а затем забудьте включить его снова, останется ли он оставаться только в файле, содержащем//CHECKSTYLE.OFF:
или все последующие обработанные файлы? – Roland 30 September 2014 в 18:58@SuppressWarnings("checkstyle:VariableDeclarationUsageDistance")
работал так же хорошо, как и младший эквивалент. – Anders Rabo Thorbeck 5 December 2017 в 14:18TreeWalker
, аFileContentHolder
больше не нужен (доступен). – avandeursen 7 April 2018 в 14:26