this
- одна из неправильно понятых концепций в JavaScript, потому что она ведет себя совсем не так, как с места на место. Просто this
ссылается на «владельца» функции, которую мы сейчас выполняем.
this
помогает получить текущий объект (контекст выполнения a.k.a.), с которым мы работаем. Если вы понимаете, в каком объекте выполняется текущая функция, вы можете легко понять, что текущий this
is
var val = "window.val"
var obj = {
val: "obj.val",
innerMethod: function () {
var val = "obj.val.inner",
func = function () {
var self = this;
return self.val;
};
return func;
},
outerMethod: function(){
return this.val;
}
};
//This actually gets executed inside window object
console.log(obj.innerMethod()()); //returns window.val
//Breakdown in to 2 lines explains this in detail
var _inn = obj.innerMethod();
console.log(_inn()); //returns window.val
console.log(obj.outerMethod()); //returns obj.val
Выше мы создаем 3 переменные с одинаковым именем «val». Один в глобальном контексте, один внутри obj и другой внутри innerMethod obj. JavaScript разрешает идентификаторы в определенном контексте, поднимая цепочку областей действия из локального глобального.
Несколько мест, где this
можно дифференцировать
var status = 1;
var helper = {
status : 2,
getStatus: function () {
return this.status;
}
};
var theStatus1 = helper.getStatus(); //line1
console.log(theStatus1); //2
var theStatus2 = helper.getStatus;
console.log(theStatus2()); //1
Когда line1, JavaScript устанавливает контекст выполнения (EC) для вызова функции, устанавливая this
объекту, на который ссылается все, что было до последнего «.». поэтому в последней строке вы можете понять, что a()
был выполнен в глобальном контексте, который является window
.
this
можно использовать для ссылки на создаваемый объект
function Person(name){
this.personName = name;
this.sayHello = function(){
return "Hello " + this.personName;
}
}
var person1 = new Person('Scott');
console.log(person1.sayHello()); //Hello Scott
var person2 = new Person('Hugh');
var sayHelloP2 = person2.sayHello;
console.log(sayHelloP2()); //Hello undefined
Когда выполняется новый Person()
, создается совершенно новый объект. Вызывается Person
и его this
установлен для ссылки на этот новый объект.
function testFunc() {
this.name = "Name";
this.myCustomAttribute = "Custom Attribute";
return this;
}
var whatIsThis = testFunc();
console.log(whatIsThis); //window
var whatIsThis2 = new testFunc();
console.log(whatIsThis2); //testFunc() / object
console.log(window.myCustomAttribute); //Custom Attribute
Если мы пропустим ключевое слово new
, whatIsThis
ссылается на самый глобальный контекст, он может найти (window
)
Если обработчик события является встроенным, this
ссылается на глобальный объект
При добавлении обработчика событий через JavaScript, this
относится к элементу DOM, который генерирует событие.
.apply()
.call()
и .bind()
var that = this
в JavaScript Я вижу ошибку в следующей строке:
@ContextConfiguration(classes = [AmazonS3Config::class, VqsS3FileReader::class])
Пожалуйста, введите здесь configuration классы (а не только бобы).
Short-hot исправить тест
Создать класс (если отсутствует), например VqsS3Configration в основном модуле (например, в модуле, где у вас есть производственный код)
Создать класс, например VqsS3TestConfigration, в том же пакете с ваши тесты. Содержимое этого файла:
@org.springframework.context.annotation.Configuration // mark, that this is configuration class
@org.springframework.context.annotation.Import(VqsS3Configration::class) // it references production configuration from test configuration
@org.springframework.context.annotation.ComponentScan // ask Spring to autoload all files from the package with VqsS3TestConfigration and all child packages
class VqsS3TestConfigration {
/*put test-related beans here in future*/
}
Затем перейдите к тесту и измените объявление:
@ContextConfiguration(classes = [VqsS3TestConfigration ::class]) // we ask Spring to load configuration here
Я создал образец приложения здесь: https://github.com/ imanushin / spring-boot2-junit5-and-kotlin-integration
Пожалуйста, используйте строку .\gradlew.bat test
или gradlew.bat bootRun
в папке src. Тест проверит, что мы можем читать свойства. bootRun будет печатать автоматически загруженные свойства
Теория расточки
Прежде всего - Spring имеет классы конфигурации - они необходимы для загрузки и инициализации других классов. Вместо классов Service или Comonent основная цель классов конфигурации - просто создавать сервисы, компоненты и т. Д.
Если мы упростим алгоритм загрузки приложения Spring, это будет следующим:
3.1. Для классов, которые аннотируются с помощью @ConfigurationProperties, введите здесь пункты конфигурации
3.2. Для классов, которые аннотируются с помощью @RestController, зарегистрируйте их как контроллеры отдыха
3.N. и т. д. ...
Как понимает Spring, какая конфигурация должна быть загружена?
@ContextConfiguration
атрибут @Import
аннотацию, затем она получает детей, затем проверяет их импорт и т. д.). Поэтому в нашем случае Spring будет делать такие действия:
Хорошо, это заняло у меня весь день, но я, наконец, получил свои свойства приложения для загрузки в мой тестовый контекст. Я сделал 2 изменения:
Во-первых, я добавил аннотацию @Service к моей службе VqsS3FileReader, которую я изначально забыл. Кроме того, хотя я обновил свой тест, чтобы не вводить AmazonS3Config через конструктор, я забыл обновить мою службу, чтобы сделать то же самое. Поэтому я изменил
следующее:
class VqsS3FileReader(val amazonS3Config: AmazonS3Config) : VqsFileReader {
companion object: mu.KLogging()
...
:
@Service
class VqsS3FileReader : VqsFileReader {
companion object: mu.KLogging()
@Resource
private lateinit var amazonS3Config: AmazonS3Config
...
Наконец, я изменил свои аннотации Spring на мой тест.
из этого:
@ActiveProfiles("test")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension::class)
@ContextConfiguration(classes = [AmazonS3Config::class, VqsS3FileReader::class])
class VqsS3FileReaderTest(): TestBase() {
...
к этому:
@ActiveProfiles("test")
@SpringBootTest
@ComponentScan("com.ilmn.*")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension::class)
@EnableAutoConfiguration
@SpringJUnitConfig(SpringBootContextLoader::class)
class VqsS3FileReaderTest(): TestBase() {
...
Кажется, у меня есть необычное количество аннотаций на моем тесте сейчас ... так что я буду внимательно изучая то, что каждый из них действительно делает, и посмотрим, смогу ли я уменьшить его. Но по крайней мере мои свойства сейчас вводятся в тестовый контекст.