利用call和原型对象实现继承
1 //3.利用call和原型对象实现继承 2 //父构造函数 3 function Father(name,age){ 4 //this指向父构造函数的对象实例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //给父亲添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100万!') 14 } 15 //子构造函数 16 function Son(name,age,score){ 17 //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 var wb = new Son('小王八',8,100) 22 console.log(wb);
运行结果:
可以看到利用call可以修改父亲函数的this,使它变成子函数的this,然而继承过来的只有父亲函数里面定义的方法,父亲而外通过原型对象添加的方法,
儿子并不可以使用,与我们想的继承还是有所出入,那么这么解决呢?
直接把父亲的原型赋值给儿子好吗?
1 //3.利用call和原型对象实现继承 2 //父构造函数 3 function Father(name,age){ 4 //this指向父构造函数的对象实例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //给父亲添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100万!') 14 } 15 //子构造函数 16 function Son(name,age,score){ 17 //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 Son.prototype = Father.prototype ; 22 var wb = new Son('小王八',8,100) 23 var f = new Father('爸爸',50) 24 console.log(wb); 25 console.log(f)
运行截图:
我们可以看到父亲和儿子的对象原型_proto_好像都有了money,那是不是儿子成功继承了父亲的函数了呢?
但是由于父亲有自己的函数,那么儿子也要有自己的函数,比如考试,我们给儿子添加考试函数
//3.利用call和原型对象实现继承 //父构造函数 function Father(name,age){ //this指向父构造函数的对象实例 this.name = name ; this.age = age; this.sing = function(){ console.log('sing') } } //给父亲添加了money方法 Father.prototype.money=function(){ console.log('100万!') } //子构造函数 function Son(name,age,score){ //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法 Father.call(this,name,18); this.score = score; } Son.prototype = Father.prototype ;//把父亲的原型赋值给儿子 //给儿子的原型添加自己的方法 Son.prototype.exam = function(){ console.log('w我考了100分!') } var wb = new Son('小王八',8,100) var f = new Father('爸爸',50) console.log(wb); console.log(f)
运行结果:
从结果上面看,我们发现果然儿子要考试,添加成功,但是仔细一看,爸爸也要考试了!
为什么会这样呢,看下图
因为我们上面直接把父亲的原型对象给了儿子,其实相当于把地址直接赋给儿子了,那么儿子如果改了什么,父亲也会随之改动,不符合继承的性质。
正确方法:
1 //3.利用call和原型对象实现继承 2 //父构造函数 3 function Father(name,age){ 4 //this指向父构造函数的对象实例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //给父亲添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100万!') 14 } 15 //子构造函数 16 function Son(name,age,score){ 17 //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 //Son.prototype = Father.prototype ;//把父亲的原型赋值给儿子有问题,此处为地址赋值,会引发错误 22 Son.prototype = new Father(); 23 //给儿子的原型添加自己的方法 24 Son.prototype.exam = function(){ 25 console.log('w我考了100分!') 26 } 27 var wb = new Son('小王八',8,100) 28 var f = new Father('爸爸',50) 29 console.log(wb); 30 console.log(f)
运行结果:
我们看到儿子可以使用父亲的函数,也有了自己独特的函数。
上面实际修改了 Son.prototype = Father.prototype ;
修改后变成:Son.prototype = new Father(),实际操作如下:只是拿到了Father的实例对象,然后fanther的实例对象可以拿到father原型对象的money方法,
而且儿子添加自己的方法最多修改了father的实例对象,父亲的构造函数没有影响。
但是上面还是有问题,因为Son.prototype = new Father(),把Father的实例对象赋值给了儿子,看似所有东西都解决了,
但是儿子里面的constructor指向父亲的构造函数了,所以还需修改儿子的constructor指向自己的构造函数。
1 //3.利用call和原型对象实现继承 2 //父构造函数 3 function Father(name,age){ 4 //this指向父构造函数的对象实例 5 this.name = name ; 6 this.age = age; 7 this.sing = function(){ 8 console.log('sing') 9 } 10 } 11 //给父亲添加了money方法 12 Father.prototype.money=function(){ 13 console.log('100万!') 14 } 15 //子构造函数 16 function Son(name,age,score){ 17 //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法 18 Father.call(this,name,18); 19 this.score = score; 20 } 21 //Son.prototype = Father.prototype ;//把父亲的原型赋值给儿子有问题,此处为地址赋值,会引发错误 22 Son.prototype = new Father();//把父亲实例对象赋给儿子 23 //把对象赋给儿子后,儿子的constructor也指向父亲了,需要手动指回儿子 24 //给儿子的原型添加自己的方法 25 Son.prototype.exam = function(){ 26 console.log('w我考了100分!') 27 } 28 var wb = new Son('小王八',8,100) 29 var f = new Father('爸爸',50) 30 console.log(wb); 31 console.log('---------------开始测试----------------------') 32 console.log('------修改前儿子的constructor指向-------------') 33 console.log(Son.prototype.constructor) 34 Son.prototype.constructor = Son;//修改指向 35 console.log('------修改后儿子的constructor指向-------------') 36 console.log(Son.prototype.constructor) 37 console.log('---------------结束测试----------------------') 38 console.log(f)
运行结果:
当然这里很麻烦,因为是Es5的时候写继承必须这样,Es6就简单了!