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();
Проблема:
java.lang.ClassNotFoundException: org.glassfish.jersey.servlet.ServletContainer
указывает, что вы пытаетесь использовать сервлет Джерси 2.x, но вы поставляете лиги Джерси 1.x.
Для Джерси 1 .x вы должны сделать это следующим образом:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>sample.hello.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Для получения дополнительной информации проверьте документацию Jersey 1.x . Если вы вместо этого хотите использовать Jersey 2.x, то вам придется предоставить Jersey 2.x libs. В проекте, основанном на maven, вы можете использовать следующее:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.xx</version>
</dependency>
<!-- if you are using Jersey client specific features without the server side -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.xx</version>
</dependency>
Для Jersey 2.x вам не нужно ничего настраивать в web.xml
, достаточно предоставить класс, подобный этому :
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("rest")
public class ApplicationConfig extends Application {
}
Для получения дополнительной информации проверьте документацию Jersey .
См. также:
У меня была та же проблема с eclipse, WA-решение заключалось в том, чтобы скопировать библиотеки в WEB-INF / lib
Если вы используете функцию Джерси 2.x, используйте следующую зависимость:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.XX</version>
</dependency>
Где XX
может быть любая конкретная версия, которую вы ищете. Контейнеры Джерси .
На самом деле jersey-container-servlet
использует зависимость jersey-container-servlet-core
. Но если вы используете maven, это не имеет большого значения. Если вы просто определите использование jersey-container-servlet
, оно также автоматически загрузит зависимость.
Но для тех, кто добавляет файлы jar в свой проект вручную (т. Е. Без maven). Важно знать, что вы на самом деле нужны оба файла jar. Класс org.glassfish.jersey.servlet.ServletContainer
фактически является частью основной зависимости.
Предположим, вы используете Jersey 2.25.1, это сработало для меня - я использую веб-контейнер Apache Tomcat:
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.25.1</version>
</dependency>
NB: Замените версию версией, используемой вами
Это проблема установки eclipse, а не проблема с Джерси.
Из этого потока ClassNotFoundException: org.glassfish.jersey.servlet.ServletContainer
Щелкните правой кнопкой мыши проект проекта eclipse. Свойства -> Развертывание сборки -> Добавить -> Записи пути сборки Java -> Зависимости подгонки -> Готово.
Итак, Eclipse не использовал зависимости Gradle при запуске Apache.
Я согласен с принятым ответом. Но для меня проблема была не в этом, вместо этого мне пришлось изменить имя моего сервлета-класса: -
<servlet-class>org.glassfish.jersey.servlet.ServletContainer.class</servlet-class>
To:
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
Итак, удаление .class отлично работал в моем случае. Надеюсь, это поможет кому-то!
Ниже код работает для меня в файле web.xml
<servlet>
<servlet-name>WebService</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.example.demo.webservice</param-value>
//Package
</init-param>
<init-param>
<param-name>unit:WidgetPU</param-name>
<param-value>persistence/widget</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebService</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
в web.xml в соответствии с документами, но я не уверен, что должен бытьparam-name
. jersey.java.net/documentation/latest/deployment.html . Обновление i> Я думаю, что этоjersey.config.server.provider.packages
. – Hack-R 17 October 2016 в 20:22