Подтвердить что ты не робот

Как вызвать унаследованный JavaScript-конструктор с параметрами?

Привет,

После прочтения следующей статьи у меня возникает вопрос: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript

В примере наследования конструктор Person не принимает никаких параметров. Как бы выглядел тот же самый пример, если бы я должен был добавить его и вызвать его из конструктора Student?

Спасибо!

4b9b3361

Ответ 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]]]