浅谈JavaScript 继承机制的实现
[javascript]
function Human() { <span style="white-space:pre"> </span>//定义Human类
this.species = "Human";
}
function Sex(sex) { <span style="white-space:pre"> </span>//定义Sex类
this.sex = sex;
}
function Chinese(name,sex) {
this.name = name;
this.newMethod1 = Human; //对象冒充,指向Human对象
this.newMethod1(); //调用方法,实现继承
delete this.newMethod1; //删除该对象的引用,避免错误调用
this.newMethod2 = Sex; //对象冒充,指向Sex对象
this.newMethod2(sex); //调用方法,实现继承
delete this.newMethod2; //删除该对象的引用,避免错误调用
}
var chin1 = new Chinese("小明","Male");
function Human() { <span style="white-space:pre"> </span>//定义Human类
this.species = "Human";
}
function Sex(sex) { <span style="white-space:pre"> </span>//定义Sex类
this.sex = sex;
}
function Chinese(name,sex) {
this.name = name;
this.newMethod1 = Human; //对象冒充,指向Human对象
this.newMethod1(); //调用方法,实现继承
delete this.newMethod1; //删除该对象的引用,避免错误调用
this.newMethod2 = Sex; //对象冒充,指向Sex对象
this.newMethod2(sex); //调用方法,实现继承
delete this.newMethod2; //删除该对象的引用,避免错误调用
}
var chin1 = new Chinese("小明","Male");
对象冒充的方法很简单易懂,原理就是利用方法的调用,在函数内实现属性的定义.
而且,对象冒充还能实现多继承.但也有不好地方.
如下:
[javascript]
<script type="text/javascript">
function Human(){ <span style="white-space:pre"> </span>//定义Human类
this.species = "Human";
}
function Sex(sex) { <span style="white-space:pre"> </span>//定义Sex类
this.sex = sex;
this.species = "Animal"; //因为调用顺序,会替换Human类的species属性
}
function Chinese(name,sex){
this.name = name;
this.newMethod1 = Human; //对象冒充,指向Human对象
this.newMethod1(); //调用方法,实现继承
delete this.newMethod1; //删除该对象的引用,避免错误调用
this.newMethod2 = Sex; //对象冒充,指向Sex对象
this.newMethod2(sex); //调用方法,实现继承
delete this.newMethod2; //删除该对象的引用,避免错误调用
}
var chin1 = new Chinese("小明","Male");
<script type="text/javascript">
function Human(){ <span style="white-space:pre"> </span>//定义Human类
this.species = "Human";
}
function Sex(sex) { <span style="white-space:pre"> </span>//定义Sex类
this.sex = sex;
this.species = "Animal"; //因为调用顺序,会替换Human类的species属性
}
function Chinese(name,sex){
this.name = name;
this.newMethod1 = Human; //对象冒充,指向Human对象
this.newMethod1(); //调用方法,实现继承
delete this.newMethod1; //删除该对象的引用,避免错误调用
this.newMethod2 = Sex; //对象冒充,指向Sex对象
this.newMethod2(sex); //调用方法,实现继承
delete this.newMethod2; //删除该对象的引用,避免错误调用
}
var chin1 = new Chinese("小明","Male");
因为是通过调用函数来"继承"的,如果多继承时,父类出现同名属性时,会被优先级高的替代.
例如上面的代码中,Sex类会替换Human类的同名属性.
也可以通过call()和apply()方法来实现继承,
其实原理和对象冒充一样.
[javascript]
function Human(){ //定义Human类
this.species = "Human";
}
function Sex(sex) { //定义Sex类
this.sex = sex;
}
function Chinese(name,sex){
this.name = name;
Human.call(this); <span style="white-space:pre"> </span>//call()方法
Sex.apply(this,[sex]);<span style="white-space:pre"> </span>//apply()方法
}
var chin1 = new Chinese("小明","Male");
function Human(){ //定义Human类
this.species = "Human";
}
function Sex(sex) { //定义Sex类
this.sex = sex;
}
function Chinese(name,sex){
this.name = name;
Human.call(this); <span style="white-space:pre"> </span>//call()方法
Sex.apply(this,[sex]);<span style="white-space:pre"> </span>//apply()方法
}
var chin1 = new Chinese("小明","Male");
这里是call()和apply()方法的介绍:http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp
其实对象冒充最大的问题就是,无法通过子类找到继承的父类.
所以这并非真正意义的继承.
[javascript]
chin1 instanceof Chinese;<span style="white-space:pre"> </span>//true
chin1 instanceof Human;<span style="white-space:pre"> </span>//false
chin1 instanceof Sex;<span style="white-space:pre"> </span>//false
chin1 instanceof Chinese;<span style="white-space:pre"> </span>//true
chin1 instanceof Human;<span style="white-space:pre"> </span>//false
chin1 instanceof Sex;<span style="white-space:pre"> </span>//false
当继承的父类中有定义对应的方法时,每次定义的对象都会重新生成一个对应的方法,这样十分浪费内存,而且不便于管理.
[javascript]
function Human(){ //定义Human类
this.species = "Human";
this.fun = function() {};
}
function Sex(sex) { //定义Sex类
this.sex = sex;
}
function Chinese(name,sex){
this.name = name;
Human.call(this); //call()方法
Sex.apply(this,[sex]); //apply()方法
}
var chin1 = new Chinese("小明","Male");
var chin2 = new Chinese("小红","Female");
chin1.fun === chin2.fun; //false
function Human(){ //定义Human类
this.species = "Human";
this.fun = function() {};
}
function Sex(sex) { //定义Sex类
this.sex = sex;
}
function Chinese(name,sex){
this.name = name;
Human.call(this); //call()方法
Sex.apply(this,[sex]); //apply()方法
}
var chin1 = new Chinese("小明","Male");
var chin2 = new Chinese("小红","Female");
chin1.fun === chin2.fun; //false
因此,下面要讨论的是原型继承(prototype).
[javascript]
function Human(){ //定义Human类
this.species = "Human";
}
function Chinese(name){
this.name = name;
}
Chinese.prototype = new Human(); //原型对象指向Human类
Chinese.prototype.constructor = Chinese; //constructor属性时指向它的构造函数
var chin1 = new Chinese("小明");
chin1 instanceof Chinese; //true
chin1 instanceof Human; //true
function Human(){ //定义Human类
this.species = "Human";
}
function Chinese(name){
this.name = name;
}
Chinese.prototype = new Human(); //原型对象指向Human类
Chinese.prototype.constructor = Chinese; //constructor属性时指向它的构造函数
var chin1 = new Chinese("小明");
chin1 instanceof Chinese; //true
chin1 instanceof Human; //true
这样就实现了真正意义上的继承.
相比对象冒充的方法,这样的写法不够直观.
但同时也解决了重复生成函数的问题.
最后,把原型继承实现简单的封装:
[javascript]
Object.prototype.extendTo = function(parent) {
this.prototype = new parent();
this.prototype.constructor = this;
this.uber = parent.prototype;
}
function Human(){ //定义Human类
this.species = "Human";
this.fun = function() {
return 0;
};
}
function Chinese(name){
this.name = name;
}
Chinese.extendTo(Human); //实现继承.
var chin1 = new Chinese("小明");
Object.prototype.extendTo = function(parent) {
this.prototype = new parent();
this.prototype.constructor = this;
this.uber = parent.prototype;
}
function Human(){ //定义Human类
this.species = "Human";
this.fun = function() {
return 0;
};
}
function Chinese(name){
this.name = name;
}
Chinese.extendTo(Human); //实现继承.
var chin1 = new Chinese("小明");
上一篇: php 上载地址
下一篇: JS如何控制二级联动