#javascript #constructor #prototype #prototypal-inheritance #object-properties
#javascript #constructor #прототип #прототипирование-наследование #объект-свойства
Вопрос:
Я пытаюсь разобраться в том, как работают прототипы. У меня есть этот пример:
function Person(name) {
if (arguments.length > 0)
this.init(name);
}
Person.prototype.init = function(name) {
this.name = name();
}
Employee.prototype = new Person();
function Employee (name, id) {
if (arguments.length > 0) {
this.init(name);
this.id = id;
}
}
var employee = new Employee("frank",01);
alert(employee.name);//returns frank
Я бы попытался выяснить, как объединить первые два раздела и назначить свойство «init» в конструкторе функции. У меня есть это, но оно ничего не возвращает:
function Person(name) {
if (arguments.length > 0)
this.init = function(name) {
this.name = name;
}
}
Employee.prototype = new Person();
function Employee (name, id) {
if (arguments.length > 0) {
this.init(name);
this.id = id;
}
}
var employee = new Employee("frank",01);
alert(employee.name);//returns nothing
Я предполагаю, что я делаю что-то неправильно при назначении init, но я не знаю, что. Изменение исходного свойства на
this.init(name) = function(name) {
тоже не работает.
Комментарии:
1. Старайтесь вообще не использовать какой-либо
init
метод! Просто выполняйте работу в конструкторе!
Ответ №1:
Вы хотите передать имя инициализируемого свойства от Employee к Person?
Это делается следующим образом:
// Create a constructor-function for your Person-Object.
function Person(name) {
this.name = name;
}
// Create the constructor-function for an Employee-Object that extends Person
function Employee(name) {
// Call the constructor-function from Person
Person.call(this, name);
}
// Let the prototype of Employee be Person.prototype (Employee extends Person)
Employee.prototype = Object.create(Person.prototype);
// By changing the prototype of Employee we have lost our constructor-function Employee()
// so we have to recover it.
Employee.prototype.constructor = Employee;
Возможно, вы ожидаете, что суперконструктор будет вызываться неявно, как вы, возможно, знаете это из других языков, таких как Java. Но этого не происходит в JavaScript. Вы должны сделать это самостоятельно, вызвав
Person.call(this, name)
Есть очень хороший JavaScript-туториал по MDN, который очень помог мне разобраться в работе с прототипом:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
Взгляните на главу «Пользовательские объекты». Думаю, я не смог бы объяснить это лучше.
Ответ №2:
Во втором фрагменте кода, если вы немного изменили одну строку
Employee.prototype = new Person('bob');
код бы сработал (сотрудник по-прежнему был «откровенным»)
Проблема в вашем конструкторе
function Person(name) {
// create member 'init' ONLY if an argument was passed to the constructor
if (arguments.length > 0)
this.init = function(name) {
this.name = name;
}
}
Как было сказано в другом ответе, изменение prototype Person
изменяет все экземпляры класса Person
и
Person.prototype.init = function(name) { ... }
создает функцию-член init
в каждом экземпляре Person
. Но в вашем конструкторе есть условие, при котором init
будет создано только в том случае, если был аргумент.
Строка
Employee.prototype = new Person();
утверждает, что каждый экземпляр класса Employee
будет иметь все члены, у которых есть объект с правой стороны. В данном случае — новый экземпляр Person
Кстати, не рекомендуется определять члены функции внутри конструкторов классов, потому что при каждом вызове конструктора потребуется создавать новую функцию. В то время как в случае модификации прототипа функция создается один раз и используется совместно со всеми экземплярами объекта.