05. Enforce new
Существует серьёзная опасность, связанная с конструктором функций: если при вызове конструктора функций отсутствует ключевое слово new, то this связывается не с создаваемым объектом, а с глобальным объектом.
function Vehicle(type, wheelsCount) {
this.type = type;
this.wheelsCount = wheelsCount;
return this;
}
// Function invocation
const car = Vehicle("Car", 4);
car.type; // => 'Car'
car.wheelsCount; // => 4
car === window; // => trueСуществует два способа гарантировать это:
Не использовать
thisв конструкторе, а собирать начиная с пустого объекта и возвращать его.Проверять, что
thisуже является экземпляром нужного класса в самом начале выполнения конструктора.
Проверка на this (второй способ):
function Vehicle(type, wheelsCount) {
if (!(this instanceof Vehicle)) {
throw Error("Error: Incorrect invocation");
}
this.type = type;
this.wheelsCount = wheelsCount;
return this;
}
// Constructor invocation
const car = new Vehicle("Car", 4);
car.type; // => 'Car'
car.wheelsCount; // => 4
car instanceof Vehicle; // => true
// Function invocation. Generates an error.
const brokenCar = Vehicle("Broken Car", 3);new.target property
new.target propertyСвойство new.target позволяет определить была ли функция или конструктор вызваны с помощью оператора new.
Если функция была вызвана при помощи оператора
new, тоnew.targetвозвращает ссылку на конструктор или функцию.При обычном вызове функции
new.targetимеет значениеundefined.
function Foo() {
if (!new.target) throw "Foo() must be called with new";
console.log("Foo instantiated with new");
}
Foo(); // throws "Foo() must be called with new"
new Foo(); // logs "Foo instantiated with new"В конструкторе класса, new.target ссылается на конструктор, который был непосредственно вызван new. Это верно и для случая, когда new.target находится в конструкторе родительского класса, а тот в свою очередь вызывается из конструктора дочернего класса.
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
const a = new A(); // logs "A"
const b = new B(); // logs "B"Подробнее: MDN: new.target
Last updated
Was this helpful?