js中继承可以分为两种:对象冒充和原型链方式
一、对象冒充包括三种:临时属性方式、call()及apply()方式
1.临时属性方式:
1 function A(x){ 2 this.x=x; this.say = function(){ alert('My name is '+this.name); } 3 } 4 function B(x,y){ 5 this.tmpObj=A; 6 this.tmpObj(x); 7 delete this.tmpObj; 8 this.id = id; this.showId = function(){ alert('Good morning,Sir,My work number is '+this.id); } 9 } var simon = new B('Simon',9527); simon.say(); simon.showId();
/**/第5、6、7行:创建临时属性tmpObj引用构造函数A,然后在B内部执行,执行完后删除。当在B内部执行了 this.x=x后(这里的this是B的对象),B当然就拥有了x属性,当然B的x属性和A的x属性两者是独立,所以并不能算严格的继承。第5、6、7行有更简单的实现,就是通过call(apply)方法:A.call(this,x);
2.call()/apply()方式:实质上是改变了this指针的指向、
function Person(name){ this.name = name; this.say = function(){ alert('My name is '+this.name); } } function F2E(name,id){ Person.call(this,name); //apply()方式改成Person.apply(this,[name]); this.id = id; this.showId = function(){ alert('Good morning,Sir,My work number is '+this.id); } } var simon = new F2E('Simon',9527); simon.say(); simon.showId();
/**/call和apply都可以实现继承,唯一的一点参数不同,func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])。
通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法:
function Person(name){ this.name = name; this.say = function(){ alert('My name is '+this.name); } } Person.prototype.age = 20; Person.prototype.sayAge = function(){alert('My age is '+this.age)}; function F2E(name,id){ Person.apply(this,new Array(name)); this.id = id; this.showId = function(){ alert('Good morning,Sir,My work number is '+this.id); } } var simon = new F2E('Simon',9527); simon.sayAge(); //提示TypeError: simon.sayAge is not a function
二、原型链继承(可以继承通过prototype方式定义的变量和方法:)
一:
function Parent(){ this.name = 'mike'; } function Child(){ this.age = 12; } Child.prototype = new Parent();//Child继承Parent,通过原型,形成链条 var test = new Child(); alert(test.age); alert(test.name);//得到被继承的属性 //继续原型链继承 function Brother(){ //brother构造 this.weight = 60; } Brother.prototype = new Child();//继续原型链继承 var brother = new Brother(); alert(brother.name);//继承了Parent和Child,弹出mike alert(brother.age);//弹出12
二:
function Person(){ this.name = 'Simon'; } Person.prototype.say = function(){ alert('My name is '+this.name); } function F2E(id){ this.id = id; this.showId = function(){ alert('Good morning,Sir,My work number is '+this.id); } } F2E.prototype = new Person(); var simon = new F2E(9527); simon.say(); simon.showId(); alert(simon.hasOwnProperty('id')); //检查是否为自身属性
原型链可以理解成:js中每个对象均有一个隐藏的__proto__属性,一个实例化对象的__proto__属性指向其类的prototype方法,而这个prototype方法又可以被赋值成另一个实例化对象,这个对象的__proto__又需要指向其类,由此形成一条链,也就是前面代码中的 F2E.prototype = new Person();
缺点显而易见,原型链方式继承,就是实例化子类时不能将参数传给父类,也就是为什么实例二中的function Person()没有参数,而是直接写成了this.name=”Simon”的原因。下面的代码将不能达到预期的效果:
unction Person(name){ this.name = name; } Person.prototype.say = function(){ alert('My name is '+this.name); } function F2E(name,id){ this.id = id; this.showId = function(){ alert('Good morning,Sir,My work number is '+this.id); } } F2E.prototype = new Person(); //此处无法进行传值,this.name或者name都不行,直接写F2E.prototype = new Person('wood')是可以的,但是这样的话simon.say()就变成了My name is wood var simon = new F2E("Simon",9527); simon.say(); //弹出 My name is undefined simon.showId();
综上分析所得:javascript中最常用的继承模式 组合继承
<script type="text/javascript"> //创建基类 function Person(name, age) { this.name = name; this.age = age; } //通过原型方式给基类添加函数(这样可以服用此函数) Person.prototype.showName = function () { alert(this.name); } //创建子类 function Student(name, age, score) { this.score = score; Person.call(this,name,age); } //把父类的实例赋值给子类的原型 Student.prototype = new Person(); //通过原型方式给子类添加函数(这样可以服用此函数) Student.prototype.showScore = function () { alert(this.score); } //以下为使用 var student = new Student("zhangsan", 22, 100); student.showName(); student.showScore(); </script>
参照:http://www.jb51.net/article/24556.htm
http://www.jb51.net/article/47619.htm
https://segmentfault.com/a/1190000002440502
http://www.cnblogs.com/ljchow/archive/2010/06/08/1753526.html