Ты разрабатываешь класс Product для интернет-магазина. Нужно создавать объект из разных форматов: из JSON-строки, из CSV-строки, из объекта с другой структурой. Или нужен метод сравнения двух товаров для сортировки — он не привязан к конкретному экземпляру.
Статические методы принадлежат классу, а не экземплярам. Вызываются через имя класса, а не через this.
class MathHelper {
static PI = 3.14159 // статическое свойство
static square(x) { return x * x }
static cube(x) { return x * x * x }
}
// Вызов через класс
MathHelper.square(4) // 16
MathHelper.PI // 3.14159
// НЕ через экземпляр — они не там живут
const h = new MathHelper()
h.square(4) // TypeError: h.square is not a functionФабричный метод — альтернативный способ создания объекта. Позволяет иметь несколько «конструкторов» с разной логикой:
class Product {
constructor(name, price, category) {
this.name = name
this.price = price
this.category = category
}
// Создать из JSON-строки
static fromJSON(json) {
const data = typeof json === 'string' ? JSON.parse(json) : json
return new Product(data.name, data.price, data.category)
}
// Создать из CSV-строки "MacBook Pro,189990,laptops"
static fromCSV(csv) {
const [name, price, category] = csv.split(',')
return new Product(name.trim(), Number(price), category.trim())
}
// Минимальный продукт (вместо Product('Без названия', 0, 'other'))
static empty() {
return new Product('Без названия', 0, 'other')
}
}
const p1 = Product.fromJSON('{"name":"iPhone","price":89990,"category":"phones"}')
const p2 = Product.fromCSV('MacBook Pro, 189990, laptops')
const p3 = Product.empty()class Request {
static count = 0
static totalTime = 0
constructor(url) {
this.url = url
Request.count++ // обращаемся через имя класса, не this
}
static getStats() {
return {
count: Request.count,
avgTime: Request.count > 0 ? Request.totalTime / Request.count : 0,
}
}
}
new Request('/api/users')
new Request('/api/products')
console.log(Request.getStats()) // { count: 2, avgTime: 0 }class User {
constructor(name, age, rating) {
this.name = name
this.age = age
this.rating = rating
}
static compareByAge(a, b) { return a.age - b.age }
static compareByRating(a, b) { return b.rating - a.rating } // убывание
static compareByName(a, b) { return a.name.localeCompare(b.name) }
}
const users = [
new User('Олег', 35, 4.2),
new User('Анна', 25, 4.8),
new User('Иван', 30, 4.5),
]
users.sort(User.compareByRating)
console.log(users.map(u => u.name)) // ['Анна', 'Иван', 'Олег']class Shape {
constructor(color) { this.color = color }
static create(color) { return new this(color) } // this — это сам класс!
}
class Circle extends Shape {
constructor(color, radius) {
super(color)
this.radius = radius
}
}
// Shape.create() — создаёт Shape
// Circle.create() — наследует, создаёт Circle (this = Circle)
const s = Shape.create('red')
const c = Circle.create('blue') // Circle.create унаследован от Shape1. Обращаются к статическому методу через экземпляр:
// Сломано:
const p = new Product('iPhone', 89990, 'phones')
const p2 = p.fromJSON(json) // TypeError: p.fromJSON is not a function
// Исправлено:
const p2 = Product.fromJSON(json) // вызов через класс2. В статическом методе используют this как экземпляр:
// Сломано — this в статическом методе это сам класс, не экземпляр:
class Product {
static compareByPrice(a, b) {
return this.price - b.price // this не тот экземпляр, что думаешь!
}
}
// Исправлено:
static compareByPrice(a, b) {
return a.price - b.price // используй параметры
}3. Хранят мутабельные данные в статических свойствах — общие для всех:
// Осторожно — cache общий для всех использований класса:
class Cache {
static data = {} // одна копия на весь класс, не на экземпляр!
}User.fromOAuth(profile), Product.fromAmazonAPI(data)Product.sortByPrice передаётся в .sort()DateUtils.format(), StringUtils.truncate() — чистые функции в классеinstance — один объект на всё приложениеComponent.getDerivedStateFromProps — статический lifecycle-методКласс Product с фабричными методами, компараторами и счётчиком
class Product {
static count = 0
constructor(name, price, category, inStock = true) {
this.id = ++Product.count
this.name = name
this.price = price
this.category = category
this.inStock = inStock
}
// Фабричный метод из JSON (строка или объект)
static fromJSON(json) {
const d = typeof json === 'string' ? JSON.parse(json) : json
return new Product(d.name, d.price, d.category, d.inStock ?? true)
}
// Фабричный метод из CSV "MacBook Pro,189990,laptops"
static fromCSV(csv) {
const parts = csv.split(',').map(s => s.trim())
return new Product(parts[0], Number(parts[1]), parts[2])
}
// Компараторы для сортировки
static byPriceAsc(a, b) { return a.price - b.price }
static byPriceDesc(a, b) { return b.price - a.price }
static byName(a, b) { return a.name.localeCompare(b.name, 'ru') }
// Утилиты
static getTotal(products) {
return products.reduce((sum, p) => sum + p.price, 0)
}
static filterAvailable(products) {
return products.filter(p => p.inStock)
}
toString() {
return `[${this.id}] ${this.name} — ${this.price.toLocaleString('ru-RU')} ₽`
}
}
// Создание из разных источников
const p1 = new Product('MacBook Pro', 189990, 'laptops')
const p2 = Product.fromJSON({ name: 'iPhone 15', price: 89990, category: 'phones' })
const p3 = Product.fromJSON('{"name":"AirPods Pro","price":24990,"category":"audio"}')
const p4 = Product.fromCSV('Magic Mouse, 8990, accessories')
const p5 = new Product('Старый товар', 100, 'misc', false) // нет в наличии
console.log('Создано товаров:', Product.count) // 5
const catalog = [p1, p2, p3, p4, p5]
// Доступные товары
const available = Product.filterAvailable(catalog)
console.log('В наличии:', available.length) // 4
// Сортировка по цене
const sorted = [...available].sort(Product.byPriceDesc)
console.log('\nПо убыванию цены:')
sorted.forEach(p => console.log(' ', p.toString()))
// Итого
const total = Product.getTotal(available)
console.log('\nСумма каталога:', total.toLocaleString('ru-RU') + ' ₽')Ты разрабатываешь класс Product для интернет-магазина. Нужно создавать объект из разных форматов: из JSON-строки, из CSV-строки, из объекта с другой структурой. Или нужен метод сравнения двух товаров для сортировки — он не привязан к конкретному экземпляру.
Статические методы принадлежат классу, а не экземплярам. Вызываются через имя класса, а не через this.
class MathHelper {
static PI = 3.14159 // статическое свойство
static square(x) { return x * x }
static cube(x) { return x * x * x }
}
// Вызов через класс
MathHelper.square(4) // 16
MathHelper.PI // 3.14159
// НЕ через экземпляр — они не там живут
const h = new MathHelper()
h.square(4) // TypeError: h.square is not a functionФабричный метод — альтернативный способ создания объекта. Позволяет иметь несколько «конструкторов» с разной логикой:
class Product {
constructor(name, price, category) {
this.name = name
this.price = price
this.category = category
}
// Создать из JSON-строки
static fromJSON(json) {
const data = typeof json === 'string' ? JSON.parse(json) : json
return new Product(data.name, data.price, data.category)
}
// Создать из CSV-строки "MacBook Pro,189990,laptops"
static fromCSV(csv) {
const [name, price, category] = csv.split(',')
return new Product(name.trim(), Number(price), category.trim())
}
// Минимальный продукт (вместо Product('Без названия', 0, 'other'))
static empty() {
return new Product('Без названия', 0, 'other')
}
}
const p1 = Product.fromJSON('{"name":"iPhone","price":89990,"category":"phones"}')
const p2 = Product.fromCSV('MacBook Pro, 189990, laptops')
const p3 = Product.empty()class Request {
static count = 0
static totalTime = 0
constructor(url) {
this.url = url
Request.count++ // обращаемся через имя класса, не this
}
static getStats() {
return {
count: Request.count,
avgTime: Request.count > 0 ? Request.totalTime / Request.count : 0,
}
}
}
new Request('/api/users')
new Request('/api/products')
console.log(Request.getStats()) // { count: 2, avgTime: 0 }class User {
constructor(name, age, rating) {
this.name = name
this.age = age
this.rating = rating
}
static compareByAge(a, b) { return a.age - b.age }
static compareByRating(a, b) { return b.rating - a.rating } // убывание
static compareByName(a, b) { return a.name.localeCompare(b.name) }
}
const users = [
new User('Олег', 35, 4.2),
new User('Анна', 25, 4.8),
new User('Иван', 30, 4.5),
]
users.sort(User.compareByRating)
console.log(users.map(u => u.name)) // ['Анна', 'Иван', 'Олег']class Shape {
constructor(color) { this.color = color }
static create(color) { return new this(color) } // this — это сам класс!
}
class Circle extends Shape {
constructor(color, radius) {
super(color)
this.radius = radius
}
}
// Shape.create() — создаёт Shape
// Circle.create() — наследует, создаёт Circle (this = Circle)
const s = Shape.create('red')
const c = Circle.create('blue') // Circle.create унаследован от Shape1. Обращаются к статическому методу через экземпляр:
// Сломано:
const p = new Product('iPhone', 89990, 'phones')
const p2 = p.fromJSON(json) // TypeError: p.fromJSON is not a function
// Исправлено:
const p2 = Product.fromJSON(json) // вызов через класс2. В статическом методе используют this как экземпляр:
// Сломано — this в статическом методе это сам класс, не экземпляр:
class Product {
static compareByPrice(a, b) {
return this.price - b.price // this не тот экземпляр, что думаешь!
}
}
// Исправлено:
static compareByPrice(a, b) {
return a.price - b.price // используй параметры
}3. Хранят мутабельные данные в статических свойствах — общие для всех:
// Осторожно — cache общий для всех использований класса:
class Cache {
static data = {} // одна копия на весь класс, не на экземпляр!
}User.fromOAuth(profile), Product.fromAmazonAPI(data)Product.sortByPrice передаётся в .sort()DateUtils.format(), StringUtils.truncate() — чистые функции в классеinstance — один объект на всё приложениеComponent.getDerivedStateFromProps — статический lifecycle-методКласс Product с фабричными методами, компараторами и счётчиком
class Product {
static count = 0
constructor(name, price, category, inStock = true) {
this.id = ++Product.count
this.name = name
this.price = price
this.category = category
this.inStock = inStock
}
// Фабричный метод из JSON (строка или объект)
static fromJSON(json) {
const d = typeof json === 'string' ? JSON.parse(json) : json
return new Product(d.name, d.price, d.category, d.inStock ?? true)
}
// Фабричный метод из CSV "MacBook Pro,189990,laptops"
static fromCSV(csv) {
const parts = csv.split(',').map(s => s.trim())
return new Product(parts[0], Number(parts[1]), parts[2])
}
// Компараторы для сортировки
static byPriceAsc(a, b) { return a.price - b.price }
static byPriceDesc(a, b) { return b.price - a.price }
static byName(a, b) { return a.name.localeCompare(b.name, 'ru') }
// Утилиты
static getTotal(products) {
return products.reduce((sum, p) => sum + p.price, 0)
}
static filterAvailable(products) {
return products.filter(p => p.inStock)
}
toString() {
return `[${this.id}] ${this.name} — ${this.price.toLocaleString('ru-RU')} ₽`
}
}
// Создание из разных источников
const p1 = new Product('MacBook Pro', 189990, 'laptops')
const p2 = Product.fromJSON({ name: 'iPhone 15', price: 89990, category: 'phones' })
const p3 = Product.fromJSON('{"name":"AirPods Pro","price":24990,"category":"audio"}')
const p4 = Product.fromCSV('Magic Mouse, 8990, accessories')
const p5 = new Product('Старый товар', 100, 'misc', false) // нет в наличии
console.log('Создано товаров:', Product.count) // 5
const catalog = [p1, p2, p3, p4, p5]
// Доступные товары
const available = Product.filterAvailable(catalog)
console.log('В наличии:', available.length) // 4
// Сортировка по цене
const sorted = [...available].sort(Product.byPriceDesc)
console.log('\nПо убыванию цены:')
sorted.forEach(p => console.log(' ', p.toString()))
// Итого
const total = Product.getTotal(available)
console.log('\nСумма каталога:', total.toLocaleString('ru-RU') + ' ₽')Ты разрабатываешь класс для работы с валютой в финтех-приложении. Создай класс `Money` с: - Полем `amount` (число) и `currency` (строка: 'RUB', 'USD', 'EUR') - Статическими фабричными методами: `rub(amount)`, `usd(amount)`, `eur(amount)` - Статическим методом `convert(money, toCurrency, rates)` — конвертация по курсу - Методом экземпляра `format()` — форматирует как "1 000 ₽", "100 $", "85 €" Таблица курсов: `rates = { RUB: 1, USD: 90, EUR: 100 }` (относительно рубля).
static usd(amount): return new Money(amount, "USD"). convert: inRub = money.amount * rates[money.currency], converted = inRub / rates[toCurrency]. format: сначала символ из объекта symbols, затем toLocaleString.