javascript继承分析
Posted vsmart
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript继承分析相关的知识,希望对你有一定的参考价值。
一,传统JS继承方法:
1,原型式继承:
//声明父类 function Person(name,age){ this.name = name; this.age = age; this.flag = true; } // 给父类添加方法 Person.prototype.sayName = function(){ console.log(this.name); } //实例化父类 var person = new Person(‘zhl‘,30); //调用父类方法 person.sayName(); // zhl // 声明子类 function Worker(name,age,work){ this.name = name; this.age = age; this.work = work; } //原型式继承 其实就是子类的原型指向父类的一个实例 Worker.prototype = new Person(); //给子类添加方法 Worker.prototype.sayWork = function(){ console.log(this.work); } //实例化一个子类 var worker = new Worker(‘vsmart‘,32,‘itcoder‘); //调用子类方法 worker.sayName(); // vsmart worker.sayWork(); // itcoder
貌似可以用了,不要高兴太早,这里是有很大的坑的!
此继承方法有几个弊端:
1,声明父类与子类的构造函数中有很多重复的初始化赋值;
2,实例化子类的对象 flag 属性竟然是 true
然而这个属性本身子类并没有初始化,哪来的?
console.log(worker.flag) //true
console.log(Worker.prototype.flag) //true
哦,原来是从子类的原型上查找到的,也就是从父类的一个实例上获取到的;
本来我们要做到 属性与方法分离的,现在呢,这个属性竟然在原型上,原型应该只放方法才对。
3,子类的构造函数 constructor 竟然指向了 父类的 constructor,这个指向错误将来势必会带来耦合
console.log(worker.constructor) //
function Person(name,age){ this.name = name; this.age = age; this.flag = true; }
综合以上几点我们要做优化;
1,我们可以借用父类的构造函数初始化子类的构造函数 利用 apply 或 call 改变指向
2,我们要重新改变子类的构造函数指向
//声明父类 function Person(name,age){ this.name = name; this.age = age; this.flag = true; } // 给父类添加方法 Person.prototype.sayName = function(){ console.log(this.name); } //实例化父类 var person = new Person(‘zhl‘,30); //调用父类方法 person.sayName(); // zhl // 声明子类 function Worker(name,age,work){ Person.apply(this,arguments); // 借用父类构造方法 this.work = work; this.flag = false; } //原型式继承 其实就是子类的原型指向父类的一个实例 Worker.prototype = new Person(); //给子类添加方法 Worker.prototype.sayWork = function(){ console.log(this.work); } //改变constructor指向 Worker.prototype.constructor = Worker; //实例化一个子类 var worker = new Worker(‘vsmart‘,32,‘itcoder‘); //调用子类方法 worker.sayName(); // vsmart worker.sayWork(); // itcoder console.log(worker.flag) //false //子类自己的属性 console.log(Worker.prototype.flag) //true 从子类原型上查找 console.log(worker.constructor) //正确指向自己的构造方法
function Worker(name,age,work){
Person.apply(this,arguments);
this.work = work;
this.flag = false;
}
2,混合拷贝继承:
所谓混合拷贝继承是指,构造函数还是借用父类的方式,但方法继承就是模拟拷贝的方式,
//声明父类 function Person(name,age){ this.name = name; this.age = age; this.flag = true; } // 给父类添加方法 Person.prototype.sayName = function(){ console.log(this.name); } //实例化父类 var person = new Person(‘zhl‘,30); //调用父类方法 //person.sayName(); // zhl // 声明子类 function Worker(name,age,work){ Person.apply(this,arguments); this.work = work; this.flag = false; } //原型式继承 其实就是子类的原型指向父类的一个实例 extends2(Worker.prototype,Person.prototype); //给子类添加方法 Worker.prototype.sayWork = function(){ console.log(this.work); } //拷贝继承核心方法 function extends2(child,parent){ for(var attr in parent){ if(parent.hasOwnProperty(attr)){ child[attr] = parent[attr]; } } } //实例化一个子类 var worker = new Worker(‘vsmart‘,32,‘itcoder‘); //调用子类方法 worker.sayName(); // vsmart worker.sayWork(); // itcoder console.log(worker.flag) //false //子类自己的属性 console.log(Worker.prototype.flag) //false 子类原型上没有查找到 console.log(worker.constructor) // /*function Worker(name,age,work){ Person.apply(this,arguments); this.work = work; this.flag = false; }*/
以上是关于javascript继承分析的主要内容,如果未能解决你的问题,请参考以下文章