[Object]继承(经典版)(二)原型链(原型继承)

作者:zccst

毫不夸张的说,这节是继承的核心所在。是重中之重。

一、原型链——将父类的实例赋给子类的prototype

function Person(name,age){
this.name = name;
this.age = age;
this.arr = [11,22,33];
this.alertName = "alertA";
this.sayHi = function(){
alert('hi');
}
}

Person.prototype.walk = function(){
alert('walk.......');
}

function Student(name,age,grade){
this.grade = grade;
}

Student.prototype = new Person();

var s1 = new Student('xiaoming',6,3);
/*
s1.walk();//walk.......
console.log(s1.name,s1.age,s1.grade);//undefined undefined 3
console.log(s1.constructor); // Person(name,age)
*/

var s2 = new Student('xiaowang',8,6);
console.log(s1.name,s1.age,s1.grade);
console.log(s2.name,s2.age,s2.grade);
s1.alertName = "alertB";
console.log(s1.alertName);
delete s1.alertName;
console.log(s1.alertName);
console.log(s2.alertName);
s1.arr.push(55);
console.log(s1.arr);
console.log(s2.arr);


Student.prototype.study = function(){
alert('I am study');
}
var p1 = new Person();
//p1.study();// p1.study is not a function

缺点:虽然s1仍然指向父类的构造函数,但修改子类的共有方法并不会对父类有所影响,但是存在一个更为严重的问题是,子类没法继承父类的特权属性和特权方法。


二、原型链与call组合


三、原型继承的其他实现方式
1,直接将父类的prototype赋给子类的prototype
缺点:父类与子类耦合太高,因为改动了子类的prototype会影响父类。即使将原型对象的constructor指向子类构造函数,但子类和父类的实例都会共有相同的constructor,这种情形下修改子类的共有方法,同时会修改了父类的共有方法,说明此法不通。


function Person(name,age){
this.name = name;
this.age = age;
this.sayHi = function(){
alert('hi');
}
}
Person.prototype.walk = function(){
alert('walk.......');
}
function Student(name,age,grade){ //子类
this.grade = grade;
}
Student.prototype = Person.prototype;

var s1 = new Student('xiaoming', 6, 3);
s1.walk();//walk.......
console.log(s1.name, s1.age, s1.grade);//undefined undefined 3
console.log(s1.constructor); // 就是Person构造函数 Person(name,age){...}

//主要缺陷:不能继承父类的特权属性和特权方法,子类的构造函数变成了Person(name,age),直接导致修改子类的原型方法时,父类也跟着修改了,耦合度太高了。
Student.prototype.study = function(){
alert('I am study');
}
var p1 = new Person();
p1.study();//I am study



2, niubility方式-利用空函数实现继承
优点:这种情况下修改Student的prototype就不会影响到Person的prototype对象了,并且,因为直接将Person的prototype赋给Empty的prototype,所以不会存在特权属性(实例属性)浪费资源的问题。这样利用空函数就能很好的解决共有方法的继承问题了。当然这时Student.prototype中的constructor是Person,所以最好加上Student.prototype.constructor = Student转换过来。


function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi=function(){
alert('hi');
}

function Student(name,age,grade){
Person.call(this,name,age);
this.grade = grade;
}

function Empty(){
}
Empty.prototype = Person.prototype;

Student.prototype = new Empty();
Student.prototype.constructor = Student;//特别关键的一句
Student.prototype.sayGrade=function(){
alert(this.grade);
}

var p1 = new Person('xiaoming',10);
var s1 = new Student('xiaohong',9,3);
console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}
console.log(s1);//Student {name="xiaohong", age=9, grade=3, 更多...}
console.log(p1.constructor);//Person(name,age) 父类的实例指向仍是父类
console.log(s1.constructor);//Student(name,age,grade) //子类的实例指向仍是子类


//以下是错误的
Student.prototype.study = function(){
alert('I am study');
}
var o1 = new Person();
o1.study();//错误
var e1 = new Empty();
e1.study();//错误



3,利用循环遍历拷贝的方法实现继承(循环将父类原型对象赋给子类原型对象)
for(var i in Person.prototype){
Student.prototype[i] = Person.prototype[i];
}
Student.prototype.constructor = Student;*/

优点:
父类原型对象的constructor指向父类构造函数,
子类原型对象的constructor指向子类构造函数,

这种循环方式,跟父类的实例属性和方法,没有任何关系,所以继承的实现用Call。


function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
};
}
Person.prototype.sayAge = function(){
alert(this.age);
}

function Student(name,age,grade){
Person.call(this, name, age);
this.grade = grade;
}
//循环copy方式继承
for(var i in Person.prototype){
alert(i);//只循环了一次,就是将父类原型方法sayAge赋给子类原型对象
Student.prototype[i] = Person.prototype[i];
}
//批注:for in只循环自定义的prototype对象属性和方法,所以并不会修改constructor指针指向

//继续添加方法
Student.prototype.sayGrade = function(){
alert(this.grade);
}

var s1 = new Student("zheng", 30, 3);
console.log(s1);
console.log(s1.constructor);
s1.sayGrade();

var p1 = new Person("aliali", 50);
console.log(p1);
console.log(p1.constructor);
//p1.sayGrade();

其实,父类和子类是没有任何关系的,唯一的联系是子类的prototype


如果您觉得本文的内容对您的学习有所帮助,您可以微信:
[img]http://dl2.iteye.com/upload/attachment/0109/0668/fb266dfa-95ca-3d09-b41e-5f04a19ba9a1.png[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值