js继承

问题:为什么要继承?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设计模式》

 

你可能感兴趣的:(js)