В Spotify плеер знает свой текущий трек, громкость и состояние. Когда вы нажимаете «пауза», плеер обращается к своим же данным: this.isPlaying = false. Ключевое слово this внутри метода ссылается на объект, которому принадлежит этот метод. Без this методы не могли бы обращаться к данным своего объекта.
Если у объекта есть данные и методы, методам нужен способ добраться до данных того же объекта. this — это автоматическая ссылка на «хозяина» вызова.
const player = {
track: 'Bohemian Rhapsody',
volume: 80,
isPlaying: false,
play() {
this.isPlaying = true
console.log(`Играет: ${this.track}`) // this = player
},
setVolume(level) {
this.volume = Math.min(100, Math.max(0, level))
}
}
player.play() // 'Играет: Bohemian Rhapsody'
console.log(player.isPlaying) // trueЕсли метод возвращает this, можно вызывать методы цепочкой:
const query = {
table: '',
conditions: [],
_limit: null,
from(table) {
this.table = table
return this // возвращаем this для цепочки
},
where(condition) {
this.conditions.push(condition)
return this
},
limit(n) {
this._limit = n
return this
},
build() {
let sql = `SELECT * FROM ${this.table}`
if (this.conditions.length) sql += ` WHERE ${this.conditions.join(' AND ')}`
if (this._limit) sql += ` LIMIT ${this._limit}`
return sql
}
}
console.log(
query.from('users').where('age > 18').where('active = 1').limit(10).build()
)
// SELECT * FROM users WHERE age > 18 AND active = 1 LIMIT 10Если метод отцепить от объекта и вызвать отдельно — this теряется:
const user = {
name: 'Алексей',
greet() {
return `Привет, я ${this.name}`
}
}
const greet = user.greet // копируем ссылку на функцию
greet() // 'Привет, я undefined' — this потерян!
// В строгом режиме — TypeError: Cannot read properties of undefinedСтрелочные функции не имеют своего this — они берут его из внешней области:
const timer = {
count: 0,
start() {
// ОШИБКА: обычная функция теряет this
setInterval(function() {
this.count++ // this здесь — undefined (strict) или window
}, 1000)
// ВЕРНО: стрелочная берёт this из start() — то есть timer
setInterval(() => {
this.count++ // this = timer
}, 1000)
}
}Ошибка 1: передача метода как коллбэк
// Сломано:
const cart = {
items: ['Ноутбук', 'Мышь'],
prefix: 'Товар',
printAll() {
this.items.forEach(function(item) {
console.log(this.prefix + ': ' + item) // this потерян!
})
}
}
// Исправлено — стрелочная функция:
printAll() {
this.items.forEach(item => {
console.log(this.prefix + ': ' + item) // this = cart
})
}Ошибка 2: деструктуризация метода
const { greet } = user // то же что const greet = user.greet
greet() // this потерян!Ошибка 3: this в обычной функции (не методе)
function show() {
console.log(this) // undefined в strict mode, window в браузере
}
show() // вызов без объекта — this не определён как объект$(this) в обработчиках событий — элемент на котором сработало событиеthis.username в методах компонента — доступ к данным компонентаthis.setState() — поэтому нужен .bind(this)this в методах маршрутизатораКорзина покупок с цепочкой методов
const cart = {
items: [],
discount: 0,
add(product) {
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.qty++
} else {
this.items.push({ ...product, qty: 1 })
}
return this // цепочка
},
remove(productId) {
this.items = this.items.filter(i => i.id !== productId)
return this
},
applyDiscount(percent) {
this.discount = percent
return this
},
subtotal() {
return this.items.reduce((sum, i) => sum + i.price * i.qty, 0)
},
total() {
return Math.round(this.subtotal() * (1 - this.discount / 100))
},
summary() {
this.items.forEach(i => {
// стрелочная — this = cart
console.log(`${i.name} x${i.qty} = ${i.price * i.qty} ₽`)
})
console.log(`Итого: ${this.total()} ₽ (скидка ${this.discount}%)`)
}
}
cart
.add({ id: 1, name: 'Ноутбук', price: 75000 })
.add({ id: 2, name: 'Мышь', price: 1500 })
.add({ id: 1, name: 'Ноутбук', price: 75000 }) // +1 к qty
.applyDiscount(10)
.remove(2)
cart.summary()
// Ноутбук x2 = 150000 ₽
// Итого: 135000 ₽ (скидка 10%)В Spotify плеер знает свой текущий трек, громкость и состояние. Когда вы нажимаете «пауза», плеер обращается к своим же данным: this.isPlaying = false. Ключевое слово this внутри метода ссылается на объект, которому принадлежит этот метод. Без this методы не могли бы обращаться к данным своего объекта.
Если у объекта есть данные и методы, методам нужен способ добраться до данных того же объекта. this — это автоматическая ссылка на «хозяина» вызова.
const player = {
track: 'Bohemian Rhapsody',
volume: 80,
isPlaying: false,
play() {
this.isPlaying = true
console.log(`Играет: ${this.track}`) // this = player
},
setVolume(level) {
this.volume = Math.min(100, Math.max(0, level))
}
}
player.play() // 'Играет: Bohemian Rhapsody'
console.log(player.isPlaying) // trueЕсли метод возвращает this, можно вызывать методы цепочкой:
const query = {
table: '',
conditions: [],
_limit: null,
from(table) {
this.table = table
return this // возвращаем this для цепочки
},
where(condition) {
this.conditions.push(condition)
return this
},
limit(n) {
this._limit = n
return this
},
build() {
let sql = `SELECT * FROM ${this.table}`
if (this.conditions.length) sql += ` WHERE ${this.conditions.join(' AND ')}`
if (this._limit) sql += ` LIMIT ${this._limit}`
return sql
}
}
console.log(
query.from('users').where('age > 18').where('active = 1').limit(10).build()
)
// SELECT * FROM users WHERE age > 18 AND active = 1 LIMIT 10Если метод отцепить от объекта и вызвать отдельно — this теряется:
const user = {
name: 'Алексей',
greet() {
return `Привет, я ${this.name}`
}
}
const greet = user.greet // копируем ссылку на функцию
greet() // 'Привет, я undefined' — this потерян!
// В строгом режиме — TypeError: Cannot read properties of undefinedСтрелочные функции не имеют своего this — они берут его из внешней области:
const timer = {
count: 0,
start() {
// ОШИБКА: обычная функция теряет this
setInterval(function() {
this.count++ // this здесь — undefined (strict) или window
}, 1000)
// ВЕРНО: стрелочная берёт this из start() — то есть timer
setInterval(() => {
this.count++ // this = timer
}, 1000)
}
}Ошибка 1: передача метода как коллбэк
// Сломано:
const cart = {
items: ['Ноутбук', 'Мышь'],
prefix: 'Товар',
printAll() {
this.items.forEach(function(item) {
console.log(this.prefix + ': ' + item) // this потерян!
})
}
}
// Исправлено — стрелочная функция:
printAll() {
this.items.forEach(item => {
console.log(this.prefix + ': ' + item) // this = cart
})
}Ошибка 2: деструктуризация метода
const { greet } = user // то же что const greet = user.greet
greet() // this потерян!Ошибка 3: this в обычной функции (не методе)
function show() {
console.log(this) // undefined в strict mode, window в браузере
}
show() // вызов без объекта — this не определён как объект$(this) в обработчиках событий — элемент на котором сработало событиеthis.username в методах компонента — доступ к данным компонентаthis.setState() — поэтому нужен .bind(this)this в методах маршрутизатораКорзина покупок с цепочкой методов
const cart = {
items: [],
discount: 0,
add(product) {
const existing = this.items.find(i => i.id === product.id)
if (existing) {
existing.qty++
} else {
this.items.push({ ...product, qty: 1 })
}
return this // цепочка
},
remove(productId) {
this.items = this.items.filter(i => i.id !== productId)
return this
},
applyDiscount(percent) {
this.discount = percent
return this
},
subtotal() {
return this.items.reduce((sum, i) => sum + i.price * i.qty, 0)
},
total() {
return Math.round(this.subtotal() * (1 - this.discount / 100))
},
summary() {
this.items.forEach(i => {
// стрелочная — this = cart
console.log(`${i.name} x${i.qty} = ${i.price * i.qty} ₽`)
})
console.log(`Итого: ${this.total()} ₽ (скидка ${this.discount}%)`)
}
}
cart
.add({ id: 1, name: 'Ноутбук', price: 75000 })
.add({ id: 2, name: 'Мышь', price: 1500 })
.add({ id: 1, name: 'Ноутбук', price: 75000 }) // +1 к qty
.applyDiscount(10)
.remove(2)
cart.summary()
// Ноутбук x2 = 150000 ₽
// Итого: 135000 ₽ (скидка 10%)Создай объект todoList для управления задачами. У него есть массив items и методы: add(text) — добавляет задачу {id, text, done: false}, complete(id) — помечает задачу выполненной, remove(id) — удаляет задачу, getPending() — возвращает массив невыполненных задач. Все методы кроме getPending возвращают this для цепочки.
complete ищет задачу через find(i => i.id === id). getPending фильтрует: filter(i => !i.done). Не забудь return this в add и remove.