← Назад к вопросам

Как работает функция New?

2.0 Middle🔥 202 комментариев
#JavaScript Core

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает функция New

Функция new - это оператор в JavaScript, который создаёт новый объект и инициализирует его через конструктор. Это один из основных механизмов для создания объектов в JavaScript.

Что делает оператор new

Оператор new выполняет 4 шага:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    return `Hello, I'm ${this.name}`;
  };
}

const john = new Person('John', 30);
// Эквивалентно:
// 1. Создано новое пустое объект {}
// 2. this привязан к новому объекту
// 3. Выполнен код функции Person
// 4. Возвращен объект (если конструктор не вернёт явно что-то другое)

4 шага выполнения new

// Пошагово:
const person = new Person('John', 30);

// Шаг 1: Создаётся новый объект
const obj = {};

// Шаг 2: obj.__proto__ указывает на Person.prototype
Object.setPrototypeOf(obj, Person.prototype);
// или
obj.__proto__ = Person.prototype;

// Шаг 3: Выполняется функция с this = obj
Person.call(obj, 'John', 30);
// Внутри Person:
// this.name = 'John';
// this.age = 30;
// this.greet = function() { ... };

// Шаг 4: Возвращается obj
return obj;

Реализация new вручную

function myNew(constructor, ...args) {
  // 1. Создаём новый объект
  const obj = Object.create(constructor.prototype);

  // 2. Вызываем конструктор с this = obj
  const result = constructor.apply(obj, args);

  // 3. Если конструктор вернул объект, возвращаем его
  // Иначе возвращаем obj
  return typeof result === 'object' && result !== null ? result : obj;
}

// Использование:
const john = myNew(Person, 'John', 30);
console.log(john.name); // 'John'
console.log(john instanceof Person); // true

Прототипная цепь

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a sound');
};

const dog = new Animal('Dog');
dog.speak(); // 'Dog makes a sound'

// Объект dog имеет структуру:
// dog = {
//   name: 'Dog',
//   __proto__: Animal.prototype {
//     speak: function() { ... },
//     __proto__: Object.prototype { ... }
//   }
// }

// Когда вызываем dog.speak():
// 1. Ищем speak в самом dog - не нашли
// 2. Ищем в dog.__proto__ (Animal.prototype) - нашли!
// 3. Выполняем

Конструкторы с return

// Если конструктор явно возвращает объект:
function Box(size) {
  this.size = size;
  return {custom: 'object'}; // Возвращаем другой объект
}

const box = new Box(10);
console.log(box); // {custom: 'object'}
console.log(box.size); // undefined (this.size не использовался)

// Если конструктор возвращает примитив:
function Counter(start) {
  this.value = start;
  return 42; // Примитив - ИГНОРИРУЕТСЯ
}

const counter = new Counter(0);
console.log(counter.value); // 0 (возвращается объект, не примитив)
console.log(counter); // Counter {value: 0}

Классы (современный синтаксис new)

// До ES6 (функции-конструкторы):
function Car(brand) {
  this.brand = brand;
}

Car.prototype.drive = function() {
  console.log('Driving a ' + this.brand);
};

const myCar = new Car('Toyota');

// ES6+ (классы - синтаксический сахар над конструкторами):
class Car {
  constructor(brand) {
    this.brand = brand;
  }

  drive() {
    console.log('Driving a ' + this.brand);
  }
}

const myCar = new Car('Toyota');
// Внутри классы работают точно так же через new

Difference: new vs обычный вызов

function Greeter(name) {
  this.name = name;
}

// С new - создаётся новый объект
const person = new Greeter('John');
console.log(person.name); // 'John'
console.log(person instanceof Greeter); // true

// Без new - this = global object (или undefined в strict mode)
const person2 = Greeter('Jane');
console.log(person2); // undefined
console.log(window.name); // 'Jane' (в браузере, плохо!)

// В строгом режиме:
'use strict';
const person3 = Greeter('Bob'); // TypeError: Cannot set property of undefined

Проверка instanceof

function Shape(sides) {
  this.sides = sides;
}

const square = new Shape(4);

console.log(square instanceof Shape); // true
console.log(square instanceof Object); // true

const fake = {sides: 4}; // Просто объект
console.log(fake instanceof Shape); // false

instanceof работает через proto

function Animal() {}
function Dog() {}

Dog.prototype = Object.create(Animal.prototype);
const myDog = new Dog();

console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Animal); // true (через прототипную цепь)
console.log(myDog instanceof Object); // true

Распространённые ошибки

// Забыли new
function User(name) {
  this.name = name;
}

const user = User('John'); // Ошибка: this = window
console.log(user); // undefined
console.log(window.name); // 'John' (заменили глобальное свойство!)

// Решение 1: Явно проверить и создать
function SafeUser(name) {
  if (!(this instanceof SafeUser)) {
    return new SafeUser(name);
  }
  this.name = name;
}

const user1 = new SafeUser('John');
const user2 = SafeUser('Jane'); // Работает!

// Решение 2: Использовать классы (всегда требуют new)
class StrictUser {
  constructor(name) {
    this.name = name;
  }
}

const user3 = new StrictUser('Bob');
const user4 = StrictUser('Alice'); // TypeError: Class constructor requires 'new'

Резюме

  1. new создаёт новый объект с привязкой к constructor.prototype
  2. this указывает на новый объект внутри конструктора
  3. Если конструктор вернёт объект - вернётся он, иначе новый объект
  4. Классы - синтаксический сахар над функциями-конструкторами
  5. instanceof проверяет через proto цепь прототипов

Оператор new - основа объектно-ориентированного программирования в JavaScript.