问题:为什么要继承?js中继承的方式有哪些?

 1为什么要继承?原则是什么?

1 reduce the amount of duplicate code
2 make your objects as loosely coupled as possible

总的原则:减少重复代码,减少耦合

 

2继承的方式

2.1类式继承,一步一步来改进

2.11继承最简单的方式。

function A1(){}
A1.prototype
={}
function A2(){}
A2.prototype
=new A1;

 

2.12 继承常用的方式—组合继承

如果上面的代码中, function A1(this.colors=["red"])
这时: var a1=new A2; a1.colors.push("yellow")
    var a2=new A2; a2.colors;
这时,a2.colors的值是什么?
这时a2.colors也一起改变了。所以改进为以下方式
function A1(){}
A1.prototype
={}
function A2(){A1.call(this)}
A2.prototype
=new A1;

 

2.13  继承的完美方式—寄生式组合继承(高级2上的名字有点长,我把它叫做完美继承)

如果这样,A1.call(this)就覆盖了new A1中的值。这样是没有问题了。但是A1执行了2次!new了一次,call又执行了一次!
所以,考虑让A2.prototype的值只继承A1.prototype。A1中的内容通过A1.call来继承。这样就完美了。
那该怎么做呢?

考虑1:如果直接尝试直接将 A2.prototype=A1.prototype .这样直接引用.这样会产生问题。如果更改A2的prototype,那么A1的prototype也会改变

考虑2:如果浅拷贝:for(var i in A1.prototype) A2.prototype[i]=A1.prototype[i].这样的话1:prototype中方法不能太多。2:A1的prototype如果改动的话,A2就没法继承了。

考虑3:如果深拷贝:A2.prototype=深拷贝A1.prototype.这样还是上面的问题。

继承总结:A1的prototype中的值是可改变的,并且A1的改动会影响到A2;A2的prototype是可改变的,A2的改动不能影响到A1.

 

A2.prototype=new A1 其实就需要 A2.prototype.__proto__=A1.prototype 也就是
var temp={};temp.__proto__=A1.prototype;A2.prototype=temp 因为__proto__是隐藏属性,所以改成下面
var temp=function(){}; temp.prototype=A1.prototype; A2.prototype=new temp

最终代码如下

 

function extend(A2,A1){
var F=function(){};
F.prototype
=A1.prototype;
A2.prototype
=new F;
A2.prototype.constructor
=A2;//重建
A2.super=A1.prototype;//新建
}

function
 A1(a){this.a=a}
A1.prototype.say
=function(){}
function A2(a){A1.call(this,a)}
extend(A1,A2)
A2.prototype.say2
=function(){}

 这里指定一个super属性,这样可以减少耦合,因为在不知道A1.prototype的情况下,可以通过A2.super来访问A1.prototype

 

类式继承总结:A中的值是任意的值,不管是数组引用,或者是对象包含对象。A.prototype中的必须是方法,不能是引用,也不能是对象包含对象。

 

 2.2 原型式继承
类似继承要求我们必须创建构造函数,而原型继承则可以直接使用对象字面量形式.

var clone=function(a){function F(){};F.prototype=a;return new F;}
var g1={name:"",colors:["yellow"]}
var g2=clone(g1)
g2.name
="free";g2.colors.push("red")
var g3=clone(g1)
g3.name
="riyue";g3.colors.push("green")
//这样,name被覆盖了,但是colors是引用。colors需要被深拷贝覆盖。
//
以上就等于
function f1(){};f1.prototype={name:"",colors:["yellow"],constructor:Object}
//下面是一个改进的原型式继承,在有数组引用,或者对象中包含对象的情况下。使用函数返回值。
var b={name:function(){return ["free"]},age:22}
var b2=clone(b)
var b3=clone(b)
b2.name
=b2.name()
b2.name.push(
"free2")
console.info(b2.name,b3.name())

 

 2.3 掺元类
实现把一个函数用到多个类中。
加入我现在有一个函数M。现在要让A1和A2类有这个函数

var M=function(){}
M.prototype.serialize
=function(){var o=[];for(var i in this) o.push(i+":"+this[i]);return o.join(",");}  //一个函数。用于返回对象的每个属性
function augment(r,g){for(var i in g.prototype){if(!r.prototype[i])r.prototype[i]=g.prototype[i]}}    //实现函数
function A2(){this.a=1}
augment(A2,M)  
//实现方式
var a2=new A2
document.write(a2.serialize())  
//这个类的对象可以使用和这个函数了

 

 

参考资料:《js高级程序设计2》,《js设计模式》

 

posted on 2011-07-08 13:52  日—月  阅读(325)  评论(0编辑  收藏  举报