闲谈JS继承之基于原型链的继承
ES【百度:ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,但实际上后两者是ECMA-262标准的实现和扩展。】只支持实现继承,且主要是靠原型链来实现。
1.基于原型链的继承
(1)首先先说下构造函数、原型、实例的关系:
a.每个构造函数都有一个浏览器默认的原型对象,【构造函数的func的prototype属性指向原型对象】
b.每个原型对象有个指向构造函数的指针【原型对象的constructor属性】
c.实例都有一个指向原型对象的内部指针【[[prototype]]或_proto_】
(2)其次说下原型链的概念:
因为实例指向原型对象,所以让“子类”的原型对象作为“父类”的实例,从而指向“父类”的原型对象,层层递进形成一条实例与原型的链。PS:JS中没有类的概念,此处的子类、父类类似java中的。
(3)基于原型链的继承实现
重写“子类”原型对象,代之为“父类”的实例
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.sayhi=function(){
console.log("hi");
}
function Student(score){
this.score=score;
}
Student.prototype=new Person();//实现继承
Student.prototype.testScore=function(){
if (this.score>90) {
console.log("优秀");
}else if(this.score>75){
console.log("良好");
}else if(this.score>60){
console.log("合格");
}else{
console.log("不合格");
}
};
var wang=new Student(80);
wang.testScore();
wang.sayhi();
PS:Student.prototype=new Person();写在Student.prototype扩展之前;防止自写的Student.prototype方法被覆盖
(4)上述原型链为wang[[prototype]]--->Student的prototype对象--->Person的prototype对象--->Object.prototype【一般函数内置默认的原型对象】
此时wang的constructor【指向的构造函数指针】指向Person,因为在改写Student.prototype时,它指向了Person的prototype对象,而Person.prototype的constructor属性指向Person
(5)存在问题
原型链的继承存在引用类型值的问题,因为继承的原型属性与方法共享,所以其中的引用值类型会被修改;
在上述中添加代码:
Person.prototype.friend=["wang","zhang","li","wan"];
。。。
wang.friend.push("zhao");
var wang1=new Student(70);
console.log(wang1.friend);//[ 'wang', 'zhang', 'li', 'wan', 'zhao' ]【变量wang改写“父类”继承的friend,影响到wang1的friend】