this в JavaScript
this — это ключевое слово, которое ссылается на тот или иной объект в зависимости от того, где оно записано или как была вызвана функция, где this присутствует.
this или другими словами контекст выполнения — это одна из тем понимание которой необходимо для изучения объектно-ориентированного программирования (ООП) в JavaScript.
Синтаксис
Посмотрим чему равен this с помощью метода console.log()
console.log(this) // this === window
или запросим значение свойства объекта, предварительно установив его, как this .
let student = < name: this >console.log(student.name) // this === window
В глобальном контексте, за пределами функций this равен объекту window в независимости от того, какой режим разработки установлен строгий ‘use strict’ или нестрогий.
Кстати, уже здесь мы можем обратиться не только к объекту window в целом, но также и к его свойствам.
console.log(this.onclick) // null
this в функциях
Если this записывать в отдельной функции, то его значение не всегда равно window . В нестрогом режиме всё без сюрпризов.
function testThis() < console.log(this) >testThis() // в браузере window testThis() // в Node global
'use strict' function testThis() < console.log(this) >testThis() // undefined
Ключевое слово this всегда динамично и указывает на тот объект в контексте которого было вызвано. В примерах выше контекст глобальный оттуда мы и видим window . Кстати, если this записать в функцию, которая лежит внутри другой функции, результат будет таким же.
function testThis() < (function () < console.log(this === window) >)() > testThis() // true
Методы объекта и this
Теперь рассмотрим другой контекст отличный от глобального.
let student = < name: 'Дмитрий', course: 'HTML + CSS', level: 'junior', objMethod() < console.log(this) >> student.objMethod()
Вызывая функцию objMethod , как метод объекта student мы видим, что ключевое слово this принимает значение этого объекта, то есть значение того объекта по отношению к которому был вызван этот метод.
let student = < name: 'Дмитрий', course: 'HTML + CSS', level: 'junior', statement() < console.log(`$c уровнем $ хочет поступить на курс $`) > > student.statement()
Таким образом, мы можем обращаться через this к значениям свойств объекта через их имена. В принципе запись ниже аналогична варианту с this .
let student = < name: 'Дмитрий', course: 'HTML + CSS', level: 'junior', statement() < console.log(`$c уровнем $ хочет поступить на курс $`) > > student.statement()
Вместо this мы прописываем имя объекта, тем самым также обращаясь к его свойствам. Однако, если мы захотим эту функцию назначить нескольким объектам первый вариант отработает без ошибок в отличие от второго.
function statement() < console.log(`$c уровнем $ хочет поступить на курс $`) > let student1 = < name: 'Дмитрий', course: 'HTML + CSS', level: 'junior', statement >let student2 = < name: 'Ольга', course: 'Basic JavaScript', level: 'junior', statement >student1.statement() // Дмитрий c уровнем junior хочет поступить на курс HTML + CSS student2.statement() // Ольга c уровнем junior хочет поступить на курс Basic JavaScript
Имея в арсенале this нет надобности писать для каждого объекта одну и ту же функцию, в примере мы записали statement() один раз, а далее назначили ее двум разным объектам. При вызове метода для student1 и student2 получили корректный результат.
Работая с this стоит помнить, что ключевое слово определяется в момент вызова функции. Таким образом, если функцию положить в переменную и вызвать уже ее, результат будет отличным.
let student1 = < name: 'Пётр', statement() < console.log(`Имя студента $`) > > student1.statement() // Имя студента Дмитрий let anotherVar = student1.statement anotherVar() // Имя студента
Стрелочные функции
Стрелочная функция не имеют собственного контекста и если в таком случае прописать this то ссылаться ключевое слово будет на объект ближайший по иерархии. Такая особенность удобна, когда мы хотим передать в функцию внешний контекст.
let student = < name: 'Дмитрий', objMethod() < console.log(this) // let arrowFunc = () => console.log(this) arrowFunc() // function funcWithinFunc() < console.log(this) >funcWithinFunc() // window > > student.objMethod() // student
В первых двух случаях this ссылается на значение объекта student , в свою очередь this , записанная в функции funcWithinFunc , будет равна window .
Функция-конструктор
Функция-конструктор позволяет создавать новые объекты по шаблону на основе других данных. При вызове функции конструктора this принимает значение вновь созданного объекта, который наполняется вследствие выполнения тела функции.
function Student(name, course) < this.name = name this.course = course this.school = 'LearnJS' >let student1 = new Student('Вера', 'JavaScript Basic') console.log(student1)
Методы call() и apply()
call() и apply() позволяют явно настроить контекст выполнения функции, результатом работы методов будет выполнение этой функции. Методы идентичны между собой, единственное их различие, это формат в котором записываются аргументы, для call() через запятую, для appy() в массиве.
let student1 = let student2 = let sayName = function(course) < console.log(`$изучает $`) > sayName.call(student1, 'JS') // Степан sayName.apply(student2, ['HTML + CSS']) // Юлия
В первом случае мы определили контекст выполнения функции sayName относительно объекта student1 , во втором относительно student2 и получили в console Степан и Юлия соответственно.
Метод bind()
bind() – это встроенный метод, который также даёт возможность зафиксировать контекст выполнения, чтобы заранее быть уверенным, какое значение будет у this . В отличие от call() и apply() метод bind() возвращает новую функцию, а не вызывает изначальную.
let student1 = let student2 = let sayName = function() < console.log(this.name) >sayName.bind(student1)() // Степан sayName.bind(student2)() // Юлия
Итого
1. Ключевое слово this позволяет работать с контекстом, получая доступ до объектов, а также имеет в арсенале методы, для того, чтобы менять этот контекст.
2. this не является фиксированным и определяется во время выполнения кода. Таким образом, пока функция не вызвана this не имеет значения.
3. Стрелочные функции не имеют собственного контекста и связываются с ближайшим по иерархии.
4. bind() , call() и apply() — методы позволяющие управлять контекстом.
5. При вызове функции-конструктора this принимает значение вновь созданного объекта.
Skypro — научим с нуля