JavaScript: Оператор new
Оператор new используется для создания объектов. Операндом этого оператора должна быть функция. Функция, которая создаётся специально для работы с оператором new , называется конструктором . Конструктор используется для инициализации нового созданного объекта:
function Obj() < this.x = 5; >var o = new Obj(); alert(o.x); // 5
Работает это всё (оператор new с конструктором) следующим образом: встречая оператор new интерпретатор создаёт новый пустой объект, затем он вызывает конструктор, и передаёт ему новый созданный объект в качестве значения ключевого слова this . Внутри конструктора происходит инициализация свойств вновь созданного объекта. После того, как объект создан и инициализарован, оператор new возвращает созданный объект.
Функция, которая создаётся специально, чтобы играть роль конструктора, не должна возвращать значение с помощью инструкции return . Однако, если внутри конструктора всё же используется инструкция return , возвращаемое значение определяется по следующему правилу:
- Если return возвращает какой-либо объект, этот объект становится значением всего выражения создания объекта, а созданный с помощью оператора new объект в этом случае просто уничтожается.
- Если return возвращает значение примитивного типа то, оно просто игнорируется и возвращается объект созданный с помощью оператора new.
function Obj(num) < this.x = num; return ; > function Obj2(num) < this.x = num; return 100; >var o = new Obj(5); var o2 = new Obj2(5); alert(o.y); // 10 alert(o2.x); // 5
Если конструктору не передаётся никаких аргументов, скобки можно не ставить:
var o = new Object;
Примечание: чтобы отличать в коде обычные функции от конструкторов, имена конструкторов обычно начинают с заглавной буквы.
С этой темой смотрят:
- Операторы. Приоритет операторов
- Математические операторы
- Присваивание
- Операторы void, группировки, запятая
- Операторы сравнения
- Логические операторы
- Побитовые операторы
Копирование материалов с данного сайта возможно только с разрешения администрации сайта
и при указании прямой активной ссылки на источник.
2011 – 2024 © puzzleweb.ru | razumnikum.ru
Конструктор, оператор «new»
Обычный синтаксис <. >позволяет создать только один объект. Но зачастую нам нужно создать множество похожих, однотипных объектов, таких как пользователи, элементы меню и так далее.
Это можно сделать при помощи функции-конструктора и оператора «new» .
Функция-конструктор
Функции-конструкторы технически являются обычными функциями. Но есть два соглашения:
- Имя функции-конструктора должно начинаться с большой буквы.
- Функция-конструктор должна выполняться только с помощью оператора «new» .
function User(name) < this.name = name; this.isAdmin = false; >let user = new User("Jack"); alert(user.name); // Jack alert(user.isAdmin); // false
Когда функция вызывается как new User(. ) , происходит следующее:
- Создаётся новый пустой объект, и он присваивается this .
- Выполняется тело функции. Обычно оно модифицирует this , добавляя туда новые свойства.
- Возвращается значение this .
Другими словами, new User(. ) делает что-то вроде:
function User(name) < // this = <>; (неявно) // добавляет свойства к this this.name = name; this.isAdmin = false; // return this; (неявно) >
Таким образом, let user = new User(«Jack») возвращает тот же результат, что и:
let user = < name: "Jack", isAdmin: false >;
Теперь, если нам будет необходимо создать других пользователей, мы можем просто вызвать new User(«Ann») , new User(«Alice») и так далее. Данная конструкция гораздо удобнее и читабельнее, чем многократное создание литерала объекта.
Это и является основной целью конструкторов – реализовать код для многократного создания однотипных объектов.
Давайте ещё раз отметим – технически любая функция (кроме стрелочных функций, поскольку у них нет this ) может использоваться в качестве конструктора. Его можно запустить с помощью new , и он выполнит выше указанный алгоритм. Подобные функции должны начинаться с заглавной буквы – это общепринятое соглашение, чтобы было ясно, что функция должна вызываться с помощью «new».
new function() < … >
Если в нашем коде присутствует большое количество строк, создающих один сложный объект, то мы можем обернуть их в функцию-конструктор, которая будет немедленно вызвана, вот так:
// создаём функцию и сразу же вызываем её с помощью new let user = new function() < this.name = "John"; this.isAdmin = false; // . другой код для создания пользователя // возможна любая сложная логика и инструкции // локальные переменные и так далее >;
Такой конструктор не может быть вызван снова, так как он нигде не сохраняется, просто создаётся и тут же вызывается. Таким образом, этот трюк направлен на инкапсуляцию кода, который создаёт отдельный объект, без возможности повторного использования в будущем.
Проверка на вызов в режиме конструктора: new.target
Продвинутая возможность
Синтаксис из этого раздела используется крайне редко. Вы можете пропустить его, если не хотите углубляться в детали языка.
Используя специальное свойство new.target внутри функции, мы можем проверить, вызвана ли функция при помощи оператора new или без него.
В случае обычного вызова функции new.target будет undefined . Если же она была вызвана при помощи new , new.target будет равен самой функции.
function User() < alert(new.target); >// без "new": User(); // undefined // с "new": new User(); // function User
Это можно использовать внутри функции, чтобы узнать, была ли она вызвана при помощи new , «в режиме конструктора», или без него, «в обычном режиме».
Также мы можем сделать, чтобы вызовы с new и без него делали одно и то же:
function User(name) < if (!new.target) < // в случае, если вы вызвали меня без оператора new return new User(name); // . я добавлю new за вас >this.name = name; > let john = User("John"); // переадресовывает вызов на new User alert(john.name); // John
Такой подход иногда используется в библиотеках, чтобы сделать синтаксис более гибким. Чтобы люди могли вызывать функцию с new и без него, и она все ещё могла работать.
Впрочем, вероятно, это не очень хорошая практика использовать этот трюк везде, так как отсутствие new может ввести разработчика в заблуждение. С new мы точно знаем, что создаётся новый объект.
Возврат значения из конструктора, return
Обычно конструкторы не имеют оператора return . Их задача – записать все необходимое в this , и это автоматически становится результатом.
Но если return всё же есть, то применяется простое правило:
- При вызове return с объектом, вместо this вернётся объект.
- При вызове return с примитивным значением, оно проигнорируется.
Другими словами, return с объектом возвращает этот объект, во всех остальных случаях возвращается this .
К примеру, здесь return замещает this , возвращая объект:
function BigUser() < this.name = "John"; return < name: "Godzilla" >; // alert( new BigUser().name ); // Godzilla, получили этот объект
А вот пример с пустым return (или мы могли бы поставить примитив после return , неважно):
function SmallUser() < this.name = "John"; return; // alert( new SmallUser().name ); // John
Обычно у конструкторов отсутствует return . Здесь мы упомянули особое поведение с возвращаемыми объектами в основном для полноты картины.
Пропуск скобок
Кстати, мы можем не ставить круглые скобки после new :
let user = new User; //
Пропуск скобок считается плохой практикой, но просто чтобы вы знали, такой синтаксис разрешён спецификацией.
Создание методов в конструкторе
Использование конструкторов для создания объектов даёт большую гибкость. Функции-конструкторы могут иметь параметры, определяющие, как создавать объект и что в него записывать.
Конечно, мы можем добавить к this не только свойства, но и методы.
Например, new User(name) ниже создаёт объект с заданным name и методом sayHi :
function User(name) < this.name = name; this.sayHi = function() < alert( "Меня зовут: " + this.name ); >; > let john = new User("John"); john.sayHi(); // Меня зовут: John /* john = < name: "John", sayHi: function() < . >> */
Для создания сложных объектов есть и более продвинутый синтаксис – классы, который мы рассмотрим позже.
Итого
- Функции-конструкторы или просто конструкторы, являются обычными функциями, но существует общепринятое соглашение именовать их с заглавной буквы.
- Функции-конструкторы следует вызывать только с помощью new . Такой вызов подразумевает создание пустого this в начале и возврат заполненного в конце.
Мы можем использовать конструкторы для создания множества похожих объектов.
JavaScript предоставляет функции-конструкторы для множества встроенных объектов языка: таких как Date , Set , и других, которые нам ещё предстоит изучить.
Мы ещё вернёмся к объектам!
В этой главе мы рассмотрели только основы объектов и конструкторов. Данная информация необходима нам для дальнейшего изучения типов данных и функций в последующих главах.
Как только мы с ними разберёмся, мы вернёмся к объектам для более детального изучения в главах Прототипы, наследование и Классы.
Что делает оператор new?
Понятно, что это конструктор, который создает пустой объект и присваивает его this; присваивает свойства и методы и возвращает this.
Но что происходит когда мы в этот самый конструктор вписываем переменные, другие объекты и оперируем ими:
function Human() < let body = < legs: 2, arms: 2 >this.go = function() < this.steps = 0; if(body.legs === 2) < this.steps += 2; >this.steps += 1; > >
Правильно ли я понимаю, что создается область видимости ограниченная конструктором, в которой доступны оные переменные/объекты ?
- Вопрос задан более трёх лет назад
- 7290 просмотров
Комментировать
Решения вопроса 1

Frontend Developer
Добавлю к вышенаписанному, что работу оператора new можно симитировать следующей функцией:
function newExpression(constructor) < if ( typeof constructor !== 'function') < throw new TypeError(constructor + 'is not a constructor'); >var args = Array.prototype.slice.call(arguments, 1); var obj = Object.create(constructor.prototype); return constructor.apply(obj, args) || obj; >
Демо.
В отличии такой имитации настоящий оператор new успешно создаст экземпляр даже по забинженому на другой контекст конструктору (по факту, возвращенной привязанной функции), так как оператор new игнорирует преданное значение this. Аргументы же будут применены из [[BoundArguments]]:
var User = function(name) < this.name = name; >User.prototype.getName = function() < return this.name; >const obj = <>; User = User.bind(obj, "Sarah"); var john = new User('John'); console.log(john.getName()); // 'Sarah'
Ответ написан более трёх лет назад
Комментировать
Нравится 2 Комментировать
Ответы на вопрос 1
Stalker_RED @Stalker_RED
Когда исполняется new Foo(. ) , происходит следующее:
1. Создается новый объект, наследующий Foo.prototype.
2. Вызывается конструктор — функция Foo с указанными аргументами и this, привязанным к только что созданному объекту. new Foo эквивалентно new Foo(), то есть если аргументы не указаны, Foo вызывается без аргументов.
3. Результатом выражения new становится объект, возвращенный конструктором. Если конструктор не возвращет объект явно, используется объект из п. 1. (Обычно конструкторы не возвращают значение, но они могут делать это, если нужно переопределить обычный процесс создания объектов.)
И да, new - это не конструктор. Конструктор обычно объявлен внутри класса или прототипа.
Ответ написан более трёх лет назад
Нравится 1 12 комментариев
BB 8 @fruity4pie Автор вопроса
Да, опечатался. new - это оператор. И да, то что Вы скинули ссылку - это хорошо, но я выше описал то же самое. Главный вопрос в самом низу - "Правильно ли я понимаю, что создается область видимости ограниченная конструктором, в которой доступны оные переменные/объекты ? "
Stalker_RED @Stalker_RED
BB 8, Область видимости конечно создается, но она ограничена не конструктором, а объектом.
function Автомобиль(цвет, скорость) < this.цвет = цвет; // это конструктор автомобиля this.скорость = скорость; >
let тачка1 = new Автомобиль('красный', 'быстрый')
let тачка2 = new Автомобиль('синий', 'супербыстрый')
console.log(тачка2.цвет)
Область видимости переменной "цвет" внутри объектов "тачка1" и "тачка2" а не внутри конструктора.
Конструктор у них один и тот-же, а объекты разные, и разный цвет.
BB 8 @fruity4pie Автор вопроса
function Автомобиль(цвет, скорость) < let details = < det1 = smth; det2 = smth; . detn = smth; >this.цвет = цвет; // это конструктор автомобиля this.скорость = скорость; >
что такое в данном случае let details ??
Stalker_RED @Stalker_RED
BB 8, внутри объекта может быть множество свойств и методов.
https://learn.javascript.ru/objects-more
Вот прямо с первого пункта и начинайте, там как-раз это подробно описывается.

Кирилл Несмеянов @SerafimArts
BB 8, только не конструктором, а контекстом.
let User = (function() < function User(name) < this.name = name; >User.prototype.render() < return `My name is $`; > return User; >)(); /// let user = new User('Vasya'); let user2 = new User('Petya'); console.log(user.render()); // My name is Vasya console.log(user2.render()); // My name is Petya
Как видно из примера, function User является конструктором, но при этом у функции рендера, что в прототипе есть прямой доступ к нему. В данном случае при new контекст смещается конкретно в область видимости функции User, а весь её прототип становится виден напрямую. Если же написать просто "User('Vasya')", то this будет ссылаться на window/global.
Т.е. если ещё повториться, то new просто перемещает this в область видимости непосредственного объекта.

Как видно из примера, function User является конструктором, но при этом у функции рендера, что в прототипе есть прямой доступ к нему.
В данном случае при new контекст смещается конкретно в область видимости функции User, а весь её прототип становится виден напрямую. Если же написать просто "User('Vasya')", то this будет ссылаться на window/global.
Т.е. если ещё повториться, то new просто перемещает this в область видимости непосредственного объекта.
Глупости. Вам стоит почитать это.
Stalker_RED @Stalker_RED
Кирилл Несмеянов, перемещает this, серьезно? И так чехарда из-за разных переводов, а вы еще и свою терминологию выдумываете.

Кирилл Несмеянов @SerafimArts
Stalker_RED, this - это контекст, так? Перемещение (смена) this означает как раз "смену контекста" или привязку "this к объекту, над которым произвели операцию new". Можно как угодно, кажется, выражаться. Пусть не по чёткой терминологии, но если объяснять простыми словами, то так понятнее, разве нет?

Кирилл Несмеянов @SerafimArts
Антон Спирин, давайте по пунктам, где именно глупость?
Stalker_RED @Stalker_RED
Кирилл Несмеянов, this - это ключевое слово, ссылающееся на контекст, а не сам контекст.
Это может быть глобальный контекст, контекст созданного объекта, либо какой-то другой, привязаный при помощи bind при создании объекта. И его нельзя менять во время исполнения. И нет у него никакого "перемещения" или "смены". Если я не прав, прошу привести пример.

Кирилл Несмеянов @SerafimArts
Stalker_RED, ну это бы бесспорно имело смысл, если бы к контексту можно было бы обратиться ещё как-то, кроме как через this. Но т.к. других инструментов нет, то определение "ребинд this" и "смена контекста" вполне равноправны. А во время исполнения можно сменить только глобальный контекст (window/global) через оператор with (тут я опять использую термин "смена контекста", вместо "ребиндинга window/global", но я всё же думаю, что сумел аргументировать утверждение, что в рамках JS эти определения равноправны).

Кирилл Несмеянов, как просили, по пунктам:
1.
Как видно из примера, function User является конструктором, но при этом у функции рендера, что в прототипе есть прямой доступ к нему.

Нет никакого "прямого доступа":
В данном случае при new контекст смещается конкретно в область видимости функции User, а весь её прототип становится виден напрямую.
Нет никаких "смещений" и "видных напрямую прототипов". При вызове new лишь создается объект наследующий прототип и на нем вызывается конструктор с переданными аргументами. Затем созданный объект возвращается:
var obj = Object.create(constructor.prototype); constructor.apply(obj, arguments); return obj;
Если же написать просто "User('Vasya')", то this будет ссылаться на window/global.
Если написать "User('Vasya')", то вам, как минимум, не вернется новый объект, наследующий прототип конструктора.
Т.е. если ещё повториться, то new просто перемещает this в область видимости непосредственного объекта
Оператор new
Оператор (операторная функция) new создаёт экземпляр объекта, встроенного или определённого пользователем, имеющего конструктор.
Синтаксис
new constructor[([arguments])]
Параметры
Функция, задающая тип объекта.
Список параметров, с которыми будет вызван конструктор.
Описание
Создание объекта, определённого пользователем, требует два шага:
- Написать функцию, которая задаст тип объекта.
- Создать экземпляр объекта, используя new .
Чтобы определить новый тип объекта, создайте функцию, которая задаст его и имя и свойства. Свойство объекта также может быть объектом. Примеры приведены ниже.
Когда исполняется new Foo(. ) , происходит следующее:
- Создаётся новый объект, наследующий Foo.prototype.
- Вызывается конструктор — функция Foo с указанными аргументами и this , привязанным к только что созданному объекту. new Foo эквивалентно new Foo() , то есть если аргументы не указаны, Foo вызывается без аргументов.
- Результатом выражения new становится объект, возвращённый конструктором. Если конструктор не возвращает объект явно, используется объект из п. 1. (Обычно конструкторы не возвращают значение, но они могут делать это, если нужно переопределить обычный процесс создания объектов.)
Всегда можно добавить свойство к уже созданному объекту. Например, car1.color = "black" добавляет свойство color к объекту car1 , и присваивает ему значение " black ". Это не затрагивает другие объекты. Чтобы добавить свойство ко всем объектам типа, нужно добавлять его в определение типа Car.
Добавить свойство к ранее определённому типу можно используя свойство Function.prototype (en-US) . Это определит свойство для всех объектов, созданных этой функцией, а не только у какого-либо экземпляра. Следующий пример добавляет свойство color со значением null всем объектам типа car , а потом меняет его на " black " только у экземпляра car1 . Больше информации в статье prototype (en-US) .
function Car() > car1 = new Car(); console.log(car1.color); // undefined Car.prototype.color = null; console.log(car1.color); // null car1.color = "black"; console.log(car1.color); // black
Примеры
Тип объекта и экземпляры объекта
Предположим, нам нужен тип объекта для автомобилей. Этот тип должен называться car , и иметь свойства: марка, модель и год.
function Car(make, model, year) this.make = make; this.model = model; this.year = year; >
Теперь можно создать экземпляр типа car:
var mycar = new Car("Eagle", "Talon TSi", 1993);
Это выражение создаёт экземпляр mycar и присваивает его свойствам указанные значения. Таким образом, mycar.make принимает значение "Eagle", mycar.year принимает значение 1993, и так далее.
Можно создать любое количество экземпляров car с помощью оператора new . Например:
var kenscar = new Car("Nissan", "300ZX", 1992);
Объект в качестве свойства
Предположим, есть объект person :
function Person(name, age, sex) this.name = name; this.age = age; this.sex = sex; >
Создадим два экземпляра:
var rand = new Person("Rand McNally", 33, "M"); var ken = new Person("Ken Jones", 39, "M");
Изменим определение car , добавив свойство, указывающее владельца — owner :
function Car(make, model, year, owner) this.make = make; this.model = model; this.year = year; this.owner = owner; >
Создадим экземпляры car:
var car1 = new Car("Eagle", "Talon TSi", 1993, rand); var car2 = new Car("Nissan", "300ZX", 1992, ken);
Вместо строковых или численных значений можно передать объект как параметр. Чтобы узнать имя владельца car2 , получим доступ к свойству:
.owner.name;
Спецификации
| Specification |
|---|
| ECMAScript Language Specification # sec-new-operator |
Совместимость с браузерами
BCD tables only load in the browser
Смотрите также
- Function
- Reflect.construct()
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 7 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
MDN
Support
- Product help
- Report an issue
Our communities
Developers
- Web Technologies
- Learn Web Development
- MDN Plus
- Hacks Blog
- Website Privacy Notice
- Cookies
- Legal
- Community Participation Guidelines
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2024 by individual mozilla.org contributors. Content available under a Creative Commons license.