Что такое ключевое слово 'new' в JavaScript?
Ключевое слово new
в JavaScript может вызывать путаницу у тех, кто с ним впервые сталкивается, так как у многих складывается впечатление, что JavaScript не является объектно-ориентированным языком программирования.
- Что это такое?
- Какие проблемы оно решает?
- Когда его уместно использовать, а когда нет?
5 ответ(ов)
Предположим, у вас есть такая функция:
var Foo = function(){
this.A = 1;
this.B = 2;
};
Если вы вызовете её как обычную функцию, вот так:
Foo();
В результате выполнения этой функции два свойства (A
и B
) будут добавлены к объекту window
. Это происходит потому, что window
— это объект, который вызвал функцию в таком контексте, а this
в функции указывает на объект, который её вызвал. Это верно для JavaScript.
Теперь вызовем её с помощью new
:
var bar = new Foo();
Когда вы добавляете new
к вызову функции, создаётся новый объект (просто var bar = new Object()
), и this
внутри функции указывает на этот новый объект, который вы только что создали, а не на объект, вызвавший функцию. Таким образом, bar
теперь является объектом с свойствами A
и B
. Любая функция может быть конструктором; просто не всегда это имеет смысл.
Это используется именно для создания экземпляров объектов. Вы определяете функцию-конструктор следующим образом:
function Person(name) {
this.name = name;
}
var john = new Person('John');
Однако у ECMAScript есть дополнительное преимущество: вы можете расширять функциональность с помощью свойства .prototype
, так что мы можем сделать что-то вроде этого...
Person.prototype.getName = function() { return this.name; }
Все объекты, созданные с помощью этого конструктора, теперь будут иметь метод getName
благодаря прототипной цепочке, к которой они имеют доступ.
Резюме:
Ключевое слово new
используется в JavaScript для создания объекта на основе функции-конструктора. Ключевое слово new
должно находиться перед вызовом функции-конструктора и выполняет следующие действия:
- Создает новый объект.
- Устанавливает прототип этого объекта на свойство прототипа функции-конструктора.
- Привязывает ключевое слово
this
к вновь созданному объекту и выполняет функцию-конструктор. - Возвращает вновь созданный объект.
Пример:
function Dog(age) {
this.age = age;
}
const doggie = new Dog(12);
console.log(doggie);
console.log(Object.getPrototypeOf(doggie) === Dog.prototype); // true
Что именно происходит:
const doggie
говорит: нам нужна память для объявления переменной.- Оператор присваивания
=
говорит: мы собираемся инициализировать эту переменную выражением, находящимся после=
. - Выражение -
new Dog(12)
. Движок JavaScript видит ключевое слово new, создает новый объект и устанавливает его прототип на Dog.prototype. - Функция-конструктор выполняется с привязкой
this
к новому объекту. На данном этапе значение возраста присваивается вновь созданному объекту doggie. - Вновь созданный объект возвращается и присваивается переменной doggie.
Ключевое слово new
изменяет контекст, в котором выполняется функция, и возвращает указатель на этот новый контекст.
Когда вы не используете ключевое слово new
, контекст, в котором выполняется функция Vehicle()
, совпадает с тем контекстом, из которого вы вызываете функцию Vehicle
. В этом случае ключевое слово this
будет ссылаться на один и тот же контекст. Когда вы используете new Vehicle()
, создается новый контекст, и в этом контексте ключевое слово this
указывает на только что созданный объект. В результате выполнения вы получаете именно этот новый контекст.
В вашем коде есть две функции, func1
и func2
, которые демонстрируют разные способы работы с объектами в JavaScript. Давайте разберем предоставленный код по частям:
var func1 = function (x) { this.x = x; } // Используется только с 'new'
var func2 = function (x) { var z={}; z.x = x; return z; } // Можно использовать обоими способами
func1.prototype.y = 11;
func2.prototype.y = 12;
A1 = new func1(1); // У A1 есть A1.x И A1.y
A2 = func1(1); // Неопределено (в 'this' ссылается на 'window')
B1 = new func2(2); // У B1 есть только B1.x
B2 = func2(2); // У B2 есть только B2.x
Объяснение кода:
func1
предназначена для использования только как конструктор (с использованиемnew
). Она устанавливает значениеx
как свойство объекта, и из-за добавления свойстваy
в его прототип, экземплярA1
будет иметь доступ как кA1.x
, так и кA1.y
.- При вызове
func1(1)
безnew
, контекстthis
ссылается на глобальный объект (обычноwindow
в браузерах), что приводит к отсутствию свойств, определённых в функции. func2
позволяет создавать объекты как с использованиемnew
, так и без. Она возвращает новый объект, который содержит только значениеx
, но не имеет доступа кy
, так как это свойство добавляется к прототипу, а не непосредственно к создаваемому объекту.
Ваш вывод:
Вы правы, использование func2
даёт больше гибкости, так как позволяет создавать объекты как конструкторами, так и обычными вызовами функций. Если вам не нужно использовать прототипы, func2
— предпочтительный выбор для простоты и ясности кода.
Где найти документацию по форматированию даты в JavaScript?
В чем разница между String.slice и String.substring?
Проверка соответствия строки регулярному выражению в JS
Существует ли ссылка на "последнюю" библиотеку jQuery в Google APIs?
Как создать диалог с кнопками "Ок" и "Отмена"