Object.prototype.constructor
Повертає посилання на функцію-конструктор об'єкта
, що створила екземпляр об'єкта. Зауважте, що значення цієї властивості є посиланням на саму функцію, а не рядком, що містить ім'я функції. Значення, доступне лише для читання, мають лише примітивні значення, як то 1
, true
або "test"
.
Опис
Усі об'єкти (за виключенням об'єктів, створених через Object.create(null)
) матимуть властивість constructor
. Об'єкти, створені без явного використання функції-конструктора (тобто, об'єктними та масивними літералами), матимуть властивість constructor
, що вказує на конструктор фундаментального об'єкта для цього об'єкта.
var o = {};
o.constructor === Object; // true
var o = new Object;
o.constructor === Object; // true
var a = [];
a.constructor === Array; // true
var a = new Array;
a.constructor === Array; // true
var n = new Number(3);
n.constructor === Number; // true
Приклади
Відображення конструктора об'єкта
Наступний приклад створює конструктор Tree
та об'єкт цього типу, theTree
. Далі приклад демонструє властивість constructor
об'єкта theTree
.
function Tree(name) {
this.name = name;
}
var theTree = new Tree('Redwood');
console.log('theTree.constructor дорівнює ' + theTree.constructor);
Цей приклад виведе наступний результат:
theTree.constructor дорівнює function Tree(name) {
this.name = name;
}
Зміна конструктора об'єкта
Наступний приклад покаже як можна змінити конструктор загальних об'єктів. Тільки true
, 1
та "test"
не зміняться, оскілки їхні конструктори доступні лише для читання. Цей приклад демонструє, що не завжди безпечно покладатися на властивість об'єкта constructor
.
function Type () {}
var types = [
new Array(),
[],
new Boolean(),
true, // лишається незмінним
new Date(),
new Error(),
new Function(),
function () {},
Math,
new Number(),
1, // лишається незмінним
new Object(),
{},
new RegExp(),
/(?:)/,
new String(),
'test' // лишається незмінним
];
for (var i = 0; i < types.length; i++) {
types[i].constructor = Type;
types[i] = [types[i].constructor, types[i] instanceof Type, types[i].toString()];
}
console.log(types.join('\n'));
Цей приклад виведе наступний результат (коментарі додані для довідки):
function Type() {},false, // new Array()
function Type() {},false, // []
function Type() {},false,false // new Boolean()
function Boolean() {
[native code]
},false,true // true
function Type() {},false,Mon Sep 01 2014 16:03:49 GMT+0600 // new Date()
function Type() {},false,Error // new Error()
function Type() {},false,function anonymous() {
} // new Function()
function Type() {},false,function () {} // function () {}
function Type() {},false,[object Math] // Math
function Type() {},false,0 // new Number()
function Number() {
[native code]
},false,1 // 1
function Type() {},false,[object Object] // new Object()
function Type() {},false,[object Object] // {}
function Type() {},false,/(?:)/ // new Regexp()
function Type() {},false,/(?:)/ // /(?:)/
function Type() {},false, // new String()
function String() {
[native code]
},false,test
Зміна конструктора функції
Переважно ця властивість використовується для визначення функції як функції-конструктора з подальшим викликом її з оператором new та наслідуванням через ланцюжок прототипів.
function Parent() {}
Parent.prototype.parentMethod = function parentMethod() {};
function Child() {}
Child.prototype = Object.create(Parent.prototype); // перевизначення дочірнього прототипу на прототип Parent
Child.prototype.constructor = Child; // повернення початкового конструктора прототипу Child
Але коли нам потрібно виконувати цей останній рядок? Нажаль, відповідь - залежить від обставин.
Спробуємо визначити випадки, коли переприсвоєння початкового конструктора зіграє важливу роль, а коли воно стане додатковим непотрібним рядком коду.
Візьмемо наступний випадок: об'єкт має метод create для створення самого себе.
function Parent() {};
function CreatedConstructor() {}
CreatedConstructor.prototype = Object.create(Parent.prototype);
CreatedConstructor.prototype.create = function create() {
return new this.constructor();
}
new CreatedConstructor().create().create(); // TypeError undefined is not a function, оскільки constructor === Parent
У наведеному вище прикладі виняток виникне тому, що конструктор посилається на Parent.
Щоб уникнути цього, просто призначте потрібний конструктор, який ви збираєтесь використовувати.
function Parent() {};
function CreatedConstructor() {}
CreatedConstructor.prototype = Object.create(Parent.prototype);
CreatedConstructor.prototype.constructor = CreatedConstructor; // призначте конструктор, який будете використовувати
CreatedConstructor.prototype.create = function create() {
return new this.constructor();
}
new CreatedConstructor().create().create(); // так непогано
Гаразд, тепер зрозуміло, чому зміна конструктора може бути досить корисною.
Розглянемо інший випадок.
function ParentWithStatic() {}
ParentWithStatic.startPosition = { x: 0, y:0 };
ParentWithStatic.getStartPosition = function getStartPosition() {
return this.startPosition;
}
function Child(x, y) {
this.position = {
x: x,
y: y
};
}
Child.prototype = Object.create(ParentWithStatic.prototype);
Child.prototype.constructor = Child;
Child.prototype.getOffsetByInitialPosition = function getOffsetByInitialPosition() {
var position = this.position;
var startPosition = this.constructor.getStartPosition(); // error undefined is not a function, оскільки конструктор - Child
return {
offsetX: startPosition.x - position.x,
offsetY: startPosition.y - position.y
}
};
В цьому прикладі нам треба залишити батьківський конструктор, щоб все працювало як слід.
Висновок: ручна зміна або встановлення конструктора може призвести до різноманітних та іноді заплутаних наслідків. Щоб запобігти цьому, визначте роль конструктора у кожному конкретному випадку. В більшості випадків конструктор не використовується, і в перепризначенні немає необхідності.
Специфікації
Специфікація | Статус | Коментар |
---|---|---|
ECMAScript (ECMA-262) The definition of 'Object.prototype.constructor' in that specification. |
Living Standard | |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.prototype.constructor' in that specification. |
Standard | |
ECMAScript 5.1 (ECMA-262) The definition of 'Object.prototype.constructor' in that specification. |
Standard | |
ECMAScript 1st Edition (ECMA-262) | Standard | Початкове визначення. Реалізоване у JavaScript 1.1. |
Сумісність з веб-переглядачами
BCD tables only load in the browser