Как вызвать унаследованный JavaScript-конструктор с параметрами?
Привет,
После прочтения следующей статьи у меня возникает вопрос:
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
В примере наследования конструктор Person не принимает никаких параметров. Как бы выглядел тот же самый пример, если бы я должен был добавить его и вызвать его из конструктора Student?
Спасибо!
Ответы
Ответ 1
Ну, способ, которым вы можете повторно использовать логику конструктора Person
, вызывает его с помощью call
или apply
, например:
function Person(gender) {
this.gender = gender;
}
function Student(gender) {
Person.apply(this, arguments);
}
Student.prototype = new Person(); // make Student inherit from a Person object
Student.prototype.constructor = Student; // fix constructor property
var foo = new Student('male');
foo.gender; // "male"
foo instanceof Student; // true
foo instanceof Person; // true
Если вы хотите предотвратить выполнение конструктора Person
при вызове без аргументов (например, в строке: Student.prototype = new Person();
), вы можете его обнаружить, например:
function Person(gender) {
if (arguments.length == 0) return; // don't do anything
this.gender = gender;
}
Ответ 2
Принятый ответ кажется неправильным. На основе того, что Mozilla говорит об OO JavaScript, правильный способ сделать это:
var Person = function(firstName) {
this.firstName = firstName;
};
function Student(firstName, subject) {
// Call the parent constructor, making sure (using Function#call)
// that "this" is set correctly during the call
Person.call(this, firstName);
// Initialize our Student-specific properties
this.subject = subject;
};
// Create a Student.prototype object that inherits from Person.prototype.
// Note: A common error here is to use "new Person()" to create the
// Student.prototype. That incorrect for several reasons, not least
// that we don't have anything to give Person for the "firstName"
// argument. The correct place to call Person is above, where we call
// it from Student.
Student.prototype = Object.create(Person.prototype); // See note below
// Set the "constructor" property to refer to Student
Student.prototype.constructor = Student;
// Example usage:
var student1 = new Student("Janet", "Applied Physics");
Как вы можете ясно видеть, Mozilla указывает, что для создания Student.prototype распространенной ошибкой является использование "new Person()". Следовательно, принятый ответ вводит в заблуждение.
Я действительно протестировал это в своем текущем проекте, и путь Mozilla правильный, в то время как выше ответ не работает.
Ответ 3
// define the Person Class
function Person(name) {
this.personname = name;
}
Person.prototype.walk = function(){};
Person.prototype.sayHello = function(){
alert (this.personname );
};
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor
Полный код:
<script>
// define the Person Class
function Person(name) {
this.personname = name;
}
Person.prototype.walk = function(){};
Person.prototype.sayHello = function(){
alert (this.personname );
};
// define the Student class
function Student() {}
// inherit Person
Student.prototype = new Person("test");
// correct the constructor pointer because it points to Person
Student.prototype.constructor = Student;
// replace the sayHello method
Student.prototype.sayHello = function(){
alert('hi, I am a student and my name is \'' + this.personname + '\'' );
}
// add sayGoodBye method
Student.prototype.sayGoodBye = function(){
alert('goodBye');
}
var student1 = new Student();
student1.sayHello();
student1.sayGoodBye();
</script>
Ответ 4
Другими комментариями я создал пример, который работает для меня. Поскольку я не использовал прототип явно, я надеюсь, что я не пропущу важный момент.
// variable for tracking instantiations and checking the uniqueness of the objects
var instances = 0;
var Generic = function() {
this.instanceId = ++instances;
this.toString = function() {return 'Generic [iid='+ this.instanceId +']'};
console.log('constructor-invoke: Generic ('+ this.instanceId +')');
};
var SpecificName = function(inName) {
Generic.call(this);
this.getName = function() { return inName; };
var superToString = this.toString.bind(this); // binds the inner function 'this' to this SpecificName instance
this.toString = function() {
return 'SpecificName [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']'
}
console.log('constructor-invoke: SpecificName ('+ this.instanceId +')');
};
var SpecificNames = function(inFirstName, inLastName) {
SpecificName.call(this, inLastName +', '+ inFirstName );
var superToString = this.toString.bind(this);
this.toString = function() {
return 'SpecificNames [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']'
}
console.log('constructor-invoke: SpecificNames ('+ this.instanceId +')');
};
var g = new Generic();
var sn = new SpecificName('Run Forest Run');
var sns = new SpecificNames('Forest','Gump');
console.log('g: '+ g.toString());
console.log('sn: '+ sn.toString());
console.log('sns: '+ sns.toString());
приводит к этому выводу:
constructor-invoke: Generic (1)
constructor-invoke: Generic (2)
constructor-invoke: SpecificName (2)
constructor-invoke: Generic (3)
constructor-invoke: SpecificName (3)
constructor-invoke: SpecificNames (3)
g: Generic [iid=1]
sn: SpecificName [iid=2, name=Run Forest Run, super.toString=Generic [iid=2]]
sns: SpecificNames [iid=3, name=Gump, Forest, super.toString=SpecificName [iid=3, name=Gump, Forest, super.toString=Generic [iid=3]]]