处理self和constructor参数的Javascript原型
Javascript prototype handling self and constructor parameters
我试图理解javascript原型设计的原理,但无法使一些基本的东西发挥作用。我试图实现的一件事是,创建一个基本对象,处理构造函数输入,并根据该输入设置值,如果没有给定构造函数参数,则设置默认值。
此外,我也不太清楚如何将其存储在一个变量中,以便它指向对象的正确实例(可能是父对象)
下面是我尝试创建基本继承的两个版本。(我以前看到过第一个使用,但它不允许我使用扩展对象的基对象的构造函数来处理传递给扩展对象的构造函数参数。第二个版本。。。是我想出来的,但是。。。我从来没有见过有人使用这样的原型,我确信这是错误的方式(因为原型属性是一个函数而不是一个对象)
解决这两个问题的正确方法是什么。
var Person = function(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
}
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
}
}
var Student = function(conf) {
if (!conf) {conf = {};}
/* id like to pass this conf on to Person constructor */
this.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
}
}
Student.prototype = new Person();
var Teacher = function(conf) {
if (!conf) {conf = {};}
this.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
}
}
Teacher.prototype = new Person();
student = new Student({first_name: "Mike", last_name: "Stud"});
//student.first_name="Mike";
//student.last_name="Stud";
student.greet();
/* alerts Hi, im Mike Stud */
teacher = new Teacher();
teacher.first_name="John";
teacher.last_name="Smith";
teacher.teach();
/* alerts John Smith is ready to teach...maggots */
teacher.callback_greet ();
/* both alerted values are undefined */
//_________________________
//_______Version 2 _______
//_________________________
var Person = function(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
}
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
}
}
var Student = function(conf) {
if (!conf) {conf = {};}
this.prototype = Person;
this.prototype(conf);
this.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
}
}
var Teacher = function(conf) {
if (!conf) {conf = {};}
this.prototype = Person;
this.prototype(conf);
this.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
}
}
var Principal = function(conf) {
if (!conf) {conf = {};}
this.prototype = Teacher;
this.prototype(conf);
this.dicipline_teachers = function() {
alert( this.first_name + " " + this.last_name + " thy all mighty principal is watching you" );
}
}
student = new Student({first_name: "Mike", last_name: "Stud"});
student.greet();
/* alerts Hi, im Mike Stud */
teacher = new Teacher({first_name: "John", last_name: "Smith"});
teacher.teach();
/* alerts John Smith is ready to teach...maggots */
principal = new Principal({first_name: "David", last_name: "Faustino"});
principal.teach();/* alerts David Faustino is ready to teach...maggots */
principal.dicipline_teachers();/* David Faustino thy all mighty principal is watching you*/
好吧,您的第二个版本实际上…有点…正确!
你的片段是什么
var Student = function(conf) { this.prototype = Person; this.prototype(conf);
在这里做:
- 使用
new Student()
调用时,将Student
实例作为this
- 在实例上创建一个包含函数(在本例中为父构造函数)的属性,该函数本质上是在实例中创建一个方法
- 将其称为方法。这意味着,调用
Person
函数时,其this
指向我们这里的实例,然后Person
在该实例上进行设置
这正是我们想要的。也许除了创建不必要的属性。请注意,这个属性的名称prototype
与其函数完全无关,您也可以使用myParentConstructor
左右。
在标准的JavaScript继承中,我们做了一件与方法调用类似的事情——我们想在当前(子)实例的上调用父构造函数,以便进行设置。但是,我们使用.call()
方法。
现在我们还想使用原型。在您的代码中,所有方法greet
、report
、teach
和dicipline_teachers
都可以在实例之间共享,因此它们可以也应该在ConstructorFn.prototype
上运行。为了让所有的老师、学生和校长继承这些方法,我们需要建立一个原型链(继承层次结构)。我们不想使用new Person
,因为它会调用构造函数,并在原型对象上设置first_name
之类的东西来共享它们,但我们不希望这样。相反,我们使用Object.create
。
合在一起,你的代码看起来是这样的:
function Person(conf) {
if (!conf) {conf = {};}
var _person = this;
this.first_name = conf.first_name;
this.last_name = conf.last_name;
this.callback_greet = function() {
alert("Hi, im " + _person.first_name + " " + _person.last_name );
console.log("this:", this, " _person:", _person );
};
}
Person.prototype.greet = function() {
alert("Hi, im " + this.first_name + " " + this.last_name );
};
function Student(conf) {
Person.call(this, conf);
}
Student.prototype = Object.create(Person.prototype, {constructor:{value:Student}});
Student.prototype.report = function() {
alert( this.first_name + " " + this.last_name + " is ready to study" );
};
function Teacher(conf) {
Person.call(this, conf);
}
Teacher.prototype = Object.create(Person.prototype, {constructor:{value:Teacher}});
Teacher.prototype.teach = function() {
alert( this.first_name + " " + this.last_name + " is ready to teach...maggots" );
};
function Principal(conf) {
Teacher.call(this, conf);
}
Principal.prototype = Object.create(Teacher.prototype, {constructor:{value:Principal}});
Principal.prototype.dicipline_teachers = function() {
alert( this.first_name + " " + this.last_name + " thy all mighty principal is watching you" );
};
(1)最好在对通过的值类型进行适当的健全性检查后处理设置默认值:
var Constr = function (conf) {
if (!!conf && !(conf instanceof Object)) {
throw new Error('An invalid parameter was passed to Constr.');
}
if (!conf) { // Prevent "Can't read property 'name' of undefined."
conf = {};
}
this.name = conf.name || null; // Set defaults this way.
};
(2) 您需要使用Object.create()
和Object.apply()
来获得正确的:
var Person = function (param1, param2) {
this.param1 = param1;
this.param2 = param2;
}
Person.prototype.cough = function () {
// Do stuff.
}
var Student = function (param1, param2, paramN) {
Person.call(this, param1, param2);
this.paramN = paramN; // Define a new property on the subclass
}
// Invoke the superclass to have the subclass inherit properties and methods.
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
- 使用“;这个“;JavaScript原型方法中的关键字
- Node.js中的JavaScript原型对象效率
- 为什么要返回'这'在导致循环的JavaScript原型中
- JavaScript原型设计基础知识
- 就良好实践而言,带闭包的javascript原型是一件好事吗
- 无法从angularjs调用JavaScript原型函数
- JavaScript原型示例
- Javascript原型组织
- 未复制JavaScript原型
- JavaScript原型的意义到底是什么
- 两个对象之间的Javascript原型
- 使用特权Getter/Setter函数的JavaScript原型函数
- 语法错误,但无法调试JavaScript原型
- 澄清:Javascript原型更新混乱
- 如何进行JavaScript原型继承(原型链)
- Javascript原型通用Enquries和通过数组索引分配Id
- 理解Javascript原型继承
- JavaScript原型与实践中的对比
- JavaScript原型构造函数只调用过一次
- Javascript原型继承原型函数调用