Что делает ключевое слово `new` в JavaScript? Объясните на примерах
Как работает ключевое слово new: пошаговое объяснение
Ключевое слово new в JavaScript — это специальный оператор, который превращает обычную функцию в конструктор (фабрику объектов). Когда вы пишете new FunctionName(), JavaScript выполняет четыре важных шага:
- Создаётся новый пустой объект — простой объект
{}. - К этому объекту привязывается прототип — устанавливается связь с
FunctionName.prototype, чтобы объект наследовал методы. - Вызывается функция с
this, указывающим на новый объект — внутри функции вы можете добавлять свойства черезthis.property = value. - Возвращается созданный объект (если функция явно не возвращает другой объект).
Вот как это выглядит на практике:
function Person(name) {
// Шаг 1: создаётся {} (неявно)
// Шаг 2: {}.__proto__ = Person.prototype (неявно)
// Шаг 3: this = {} (неявно)
this.name = name; // теперь {} имеет свойство name
this.sayHello = function() {
console.log('Привет, меня зовут ' + this.name);
};
// Шаг 4: return this; (неявно)
}
const user = new Person('Анна');
console.log(user.name); // "Анна"
user.sayHello(); // "Привет, меня зовут Анна"
Почему без new не работает?
Если вызвать Person('Анна') без new, то:
thisбудет указывать на глобальный объект (windowв браузере илиglobalв Node.js)- Свойство
nameи функцияsayHelloбудут добавлены к глобальному объекту - Сама функция вернёт
undefined, так как нет явногоreturn
Прототипы и new
Одна из главных причин использовать new — это работа с прототипами. Методы, добавленные в prototype, не копируются в каждый объект, а являются общими:
function Animal(type) {
this.type = type;
}
// Добавляем метод в прототип
Animal.prototype.say = function() {
console.log('Я — ' + this.type);
};
const cat = new Animal('кошка');
const dog = new Animal('собака');
cat.say(); // "Я — кошка"
dog.say(); // "Я — собака"
// Это один и тот же метод!
console.log(cat.say === dog.say); // true
Современная альтернатива: классы (ES6+)
С появлением ES6 (2015) появился синтаксис class, который делает то же самое, но выглядит понятнее:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log('Привет, меня зовут ' + this.name);
}
}
const user = new Person('Анна');
user.sayHello(); // "Привет, меня зовут Анна"
Под капотом классы — это те же функции-конструкторы с new. Но синтаксис class считается более читаемым и безопасным (например, если забыть new, будет ошибка).
Важные моменты
- Именование: функции-конструкторы принято называть с заглавной буквы (PascalCase) — это соглашение, чтобы отличать их от обычных функций.
- Возврат объекта: если конструктор явно возвращает объект,
newвернёт этот объект, а неthis. - Стрелочные функции: их нельзя использовать как конструкторы —
newс ними вызовет ошибку.
В итоге: new — это способ сказать JavaScript: «Создай новый объект, привяжи к нему прототип и передай его как this в функцию». Без new вы просто вызываете функцию, и this теряется.
Альтернативный взгляд: фабричные функции и Object.create()
Хотя new и классы — стандартный способ создания объектов в JS, существуют альтернативы, которые могут быть удобнее в некоторых ситуациях.
Фабричная функция (Factory Function)
Это обычная функция, которая возвращает новый объект без использования new:
function createPerson(name) {
return {
name: name,
sayHello() {
console.log('Привет, меня зовут ' + this.name);
}
};
}
const user = createPerson('Анна');
user.sayHello(); // "Привет, меня зовут Анна"
Плюсы: не нужно помнить про new, нет риска испортить глобальный объект. Минус: каждый объект получает свою копию метода (больше памяти).
Object.create()
Этот метод создаёт объект с указанным прототипом:
const personProto = {
sayHello() {
console.log('Привет, меня зовут ' + this.name);
}
};
function createPerson(name) {
const obj = Object.create(personProto);
obj.name = name;
return obj;
}
const user = createPerson('Анна');
user.sayHello(); // "Привет, меня зовут Анна"
Object.create() даёт полный контроль над прототипом, но требует больше кода. Обычно на практике используют либо классы (для сложных иерархий), либо фабричные функции (для простых объектов). Выбирайте то, что понятнее вашей команде!