因此,JavaScript常被描述为基于原型的语言--每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性,原型对象也有可能拥有原型,从中继承方法和属性,以此类推。而这种关系被称为原型链。
我们需要知道的是,这些属性和方法是定义在实例的构造函数上的prototype属性,当然,实例对象也__proto__属性,是从构造函数的prototype属性派生的,即实例对象.__proto===构造函数.prototype。
从截图我们看到,person1实例除了具有Person()构造器中的属性方法外,还具有其他属性和方法,而这些则是Person()构造器原型对象Object上的成员。
通过调用valueOf,因此,我们也了解到了调用方法的过程:
1.浏览器首先检查,person1 对象是否具有可用的 valueOf() 方法。
2.如果没有,则浏览器检查 person1 对象的原型对象(即 Person)是否具有可用的 valueof() 方法。
3.如果也没有,则浏览器检查 Person() 构造器的原型对象(即 Object)是否具有可用的 valueOf() 方法。Object 具有这个方法,于是该方法被调用。
prototype属性通过对valueOf方法的调用过程,我们也就了解到了那些能被继承的属性和方法(对象中存在不能被继承的属性方法,例is()/keys())是定义在prototype属性上的。因此,在构造函数是需要被子类继承的属性方法需要定义在prototype上。
constructor属性 每个实例对象都有constructor属性,它是指向创建该实例的构造函数。
而我们也可以通过在constructor后添加()形式实现创建新实例。
通过截图我们可以了解到了,虽然已经创建了实例对象person1,当时之后再像构造器Person()prototype中添加方法,person1还是能调用,这就说明了函数调用会通过上溯原型链,从上游对象中调用方法。
如图,若在prototype上定义属性的话,则this的当前执行环境为全局,返回的为undefined。并且,在对象继承上看,一般的做法是在构造器中定义属性,在prototype属性中定义方法。 小demo--实例理解JavaScript中的继承 1.创建构造器Person并在构造器上定义方法
function Person(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
};
Person.prototype.bio = function() {
alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
};
Person.prototype.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}