Честно говоря, свойство .constructor
не имеет большого значения и имеет очень мало общего с наследованием от других объектов в JavaScript.Это просто удобный дескриптор конструктора объекта.
Например, если у вас есть экземпляр чего-либо, и вы хотите создать другой экземпляр этого объекта, но у вас нет прямого дескриптораего конструктор, вы можете сделать что-то вроде этого:
const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
const car2 = new myCar.constructor();
console.log(car2.constructor); // [Function: Racecar]
Важно понимать, что свойство .constructor
и класс объекта не являются синонимами.Как вы, возможно, уже догадались, свойство .constructor
является динамическим, как и большинство других вещей в JavaScript, поэтому его не следует использовать ни для чего, кроме проверки типов.
Также важно понимать, что .constructor
свойство не означает, что что-то является подклассом чего-то другого.На самом деле, нет надежного способа узнать, является ли что-то подклассом чего-то другого в JavaScript.Поскольку это динамический язык и поскольку существует много способов наследовать свойства от других объектов (включая копирование свойств из других объектов после создания экземпляров), безопасные подклассы не существуют в JavaScript, как они существуют в других языках.
Лучший способ узнать, является ли что-либо совместимым типом, - это проверить свойства объекта.Другими словами, тип утки.
Оператор instanceof
игнорирует свойство .constructor
.Вместо этого он проверяет, существует ли конструктор .prototype
(с проверкой идентичности) в цепочке прототипов объекта.
С помощью функций ручного конструктора наследование может запутать соединение свойства .constructor
(делая егообратитесь к неправильному конструктору).Вы можете исправить это, вручную подключив соединение.Например, канонический способ сделать это в ES5 заключается в следующем:
function Car () {}
console.log(Car.prototype.constructor); // Car
function Racecar () {}
Racecar.prototype = Object.create(Car.prototype);
// To preserve the same relationship we have with the Car
// constructor, we'll need to reassign the .prototype.constructor:
Racecar.prototype.constructor = Racecar;
var myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
Классы ES6 делают это автоматически:
// ES6
class Car {}
class Racecar extends Car {}
const myCar = new Racecar();
console.log(myCar.constructor); // [Function: Racecar]
Тем не менее, я не большой поклонниклибо функций конструктора, либо классов ES6, и я обычно мало пользуюсь свойством .constructor
.Зачем?Поскольку фабричные функции гораздо более гибкие, гораздо более мощные, и у них нет ловушек, связанных с функциями конструктора и наследованием классов.См. «Фабричные функции против функций конструктора против классов» .