本文主要是讲解如何通过prototype实现JavaScript继承,并逐步循序渐进,最终实现一个继承的通用函数。
1.首先我们定义一个父类Father,如下所示:
function Father(){运行结果如下:
this.name = "姓名";
this.age = "20";
this.setName = function(str){this.name=str};
this.getName = function(){return this.name;};
}
Father.prototype.setAge = function(age){this.age = age;};
Father.prototype.getAge = function(){return this.age;};
console.log(new Father());
Father
- age: "20"
- getName: function (){return this.name;}
- name: "姓名"
- setName: function (str){this.name=str}
可以看到Father具有age、name两个属性以及getName、setName、getAge、setAge四个方法,但是要注意的是setAge、getAge方法是放在Father.prototype中的,prototype中的方法是公共方法,也就是说在创建新的实例时,prototype中的内容不会随着新实例的创建而占用更多的内存,所以公共方法最好放到prototype中。而实例中的setName与getName方法是在实例中的,每当新实例创建时,每个新实例都会额外占用内存来存储这两个方法。
2.使用call(context,para1...)尝试实现继承
代码如下:
function Sun1(){Father.call(this);}console.log(new Sun1())
运行结果如下: Sun1
- age: "20"
- getName: function (){return this.name;}
- name: "姓名"
- setName: function (str){this.name=str}
3.尝试使用apply(context,arguments)尝试实现继承
代码如下:
function Sun2(){Father.apply(this,arguments);}console.log(new Sun2());
运行结果如下: Sun2
- age: "20"
- getName: function (){return this.name;}
- name: "姓名"
- setName: function (str){this.name=str}
4.通过更改prototype实现继承
代码如下:
function Sun3(){}Sun3.prototype = new Father();Sun3.prototype.constructor = Sun3;console.log(new Sun3());
运行结果如下: Sun3
5.继承函数的实现
既然我们知道了如何通过prototype来实现继承,那么我们就可以将该实现封装成一个函数,使得代码可重用,代码如下:
function inherit(child,parent){child.prototype = new parent();child.prototype.constructor = child;}function Sun4(){}inherit(Sun4,Father);console.log(new Sun4());运行结果如下:
6.面向对象的通用继承的实现
虽然上文已经通过inherit函数实现了继承函数,但是在使用时每次都要把父子两个类传递进去,还不够面向对象,为了更好的模拟面向对象的特性,我们再进一步进行改进,代码如下:
Function.prototype.method = function(funcName,func){this.prototype[funcName] = func;};Function.prototype.inherit = function(parent){this.prototype = new parent();this.prototype.constructor = this;};function Sun5(){}Sun5.inherit(Father);console.log(new Sun5());
运行结果如下: Sun5
Function.prototype.inherit:这一函数能用来实现单父继承。由于inherit方法是在Function的原型中的,所以使得所有的子类都能有原生的使用该inherit方法,只需要传递父类的构造函数即可。
注意:在inherit函数中调用parent 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
如果父类的构造函数中有参数,那该怎么办呢?可以这样实现,代码如下:
function Father(name,age){this.name = name;this.age = age;this.setName = function(str){this.name=str};this.getName = function(){return this.name;};}Father.prototype.setAge = function(age){this.age = age;};Father.prototype.getAge = function(){return this.age;};console.log(new Father());Function.prototype.method = function(funcName,func){this.prototype[funcName] = func;};Function.prototype.inherit = function(parent){this.prototype = new parent();this.prototype.constructor = this;};function Sun6(name,age){Father.call(this,name,age);}Sun6.inherit(Father);console.log(new Sun6("姓名",20));
运行结果如下: Sun6
- age: 20
- getName: function (){return this.name;}
- name: "姓名"
- setName: function (str){this.name=str}
这里通过call与prototype的共同使用才实现了继承。
参考:
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
http://www.w3school.com.cn/js/pro_js_inheritance_implementing.asp