最近学了 JS 的面向对象, 这篇文章主要是探讨 JS 的面向对象中继承的那些事.
JS 中继承的特点:
1, 子类继承父类;
2, 子类可以用父类的方法和属性
3, 子类的改变可以不影响父类
下面用一个例子来说明 JS 的继承
这段代码创建了一个父类以及它的原型, 同时还创建了一个子类, 并继承了父类的私有属性
- // 这是父类
- function Father(name,age,marry){
- this.name=name;
- this.age=age;
- this.marry=marry;
- }
- // 父类的原型
- Father.prototype.showName=function(){
- alert(this.name);
- }
- // 子类
- function Son(name,age,marry,weight){
- Father.call(this,name,age,marry);
- this.weight=weight;
- }
当子类 Son 想继承父类的原型时, 我的做法一开始是这么做的
- // 这是父类
- function Father(name,age,marry){
- this.name=name;
- this.age=age;
- this.marry=marry;
- }
- // 父类的原型
- Father.prototype.showName=function(){
- alert(this.name);
- }
- // 子类
- function Son(name,age,marry,weight){
- Father.call(this,name,age,marry);
- this.weight=weight;
- }
- // 错误的做法
- Son.prototype=Father.prototype;
- Son.prototype.showAge=function(){
- alert(this.age);
- }
- var father=new Father('王大锤',30,true);
- alert(father.showAge);
运行的结果可以发现, 子类原型的改变影响了父类的原型, 父类的原型中本来是没有 showAge 方法的, 这就违背了前面继承的第三个特点了.
分析原因: 上面代码的第 20 行 Son.prototype=Father.prototype; 这里的 '=' 两边都是对象, 那么它代表的意思就是引用, 如果是引用的话, 左边的对象改变, 肯定会影响了右边的对象
所以才出现了子类原型的改变影响了父类的原型.
解决办法
方法一: 核心思路, 前面的问题不是说 '=' 是引用的关系才导致问题的嘛, 那这里就保证 '=' 永远是赋值的关系, 而不是引用. 这里就定义一个 Clone() 方法, 将父类对象拷贝给子类.
Clone() 方法里用到递归的原因是, 在拷贝的过程中对象中可能嵌套对象.
- // 这是父类
- function Father(name,age,marry){
- this.name=name;
- this.age=age;
- this.marry=marry;
- }
- // 父类的原型
- Father.prototype.showName=function(){
- alert(this.name);
- }
- // 子类
- function Son(name,age,marry,weight){
- Father.call(this,name,age,marry);
- this.weight=weight;
- }
- Son.prototype=new Clone(Father.prototype);
- Son.prototype.showAge=function(){
- alert(this.age);
- }
- var father=new Father('王大锤',30,true);
- alert(father.showAge);
- // 通过克隆对象: 核心思路是保证 '=' 是赋值的关系, 而不是引用, 也就是保证 '=' 的右边不是对象
- function Clone(obj){
- for(var i=0;i<obj.length;i++){
- if(typeof(obj[key]=='object')){
- this.key=new Clone(obj[key]);
- }else{
- this.key=obj[key];
- }
- }
- }
这时候的结果父类对象的 showAge 方法是 undefined
方法二: 代码很简单, 但是很难想到, 没有第一个方法那么好理解. 核心思想: 对象自身属性的改变, 不会影响其构造函数的属性的改变.
- // 这是父类
- function Father(name,age,marry){
- this.name=name;
- this.age=age;
- this.marry=marry;
- }
- // 父类的原型
- Father.prototype.showName=function(){
- alert(this.name);
- }
- // 子类
- function Son(name,age,marry,weight){
- Father.call(this,name,age,marry);
- this.weight=weight;
- }
- function fn(){}
- fn.prototype=Father.prototype;
- Son.prototype=new fn();
- Son.prototype.showAge=function(){
- alert(this.age);
- }
- var father=new Father('王大锤',30,true);
- alert(father.showAge);
- // 通过克隆对象: 核心思路是保证 '=' 是赋值的关系, 而不是引用, 也就是保证 '=' 的右边不是对象
- // Son.prototype=new Clone(Father.prototype);
- // function Clone(obj){
- // for(var i=0;i
- // if(typeof(obj[key]=='object')){
- // this.key=new Clone(obj[key]);
- // }else{
- // this.key=obj[key];
- // }
- // }
- // }
来源: http://www.bubuko.com/infodetail-2768539.html