function Super(arg){ this.arr1 = "I'm super "+arg; } Super.prototype.show = function(){ //这个方法放到了原型对象上。 alert(this.arr1); } Super.prototype.say = function(){ alert(this.arr1); } function suber(arg){ Super.apply(this, arguments); } /*inherit函数的作用,使用一个新的空函数,来切断父类对象的原型对象与子类原型对象的直接联系,而是通过这个空构造的实例对象实现继承,这样可以避免更改子类原型的属性或者方法而影响了父类原型对象的属性或者方法。*/ function inherit(obj){ function F(){} F.prototype = obj; return new F(); } suber.prototype = inherit(Super.prototype); var sub = new suber("suber1"); var sub2 = new suber("suber2"); console.log(sub.arr1); //I'm super suber1 console.log(sub.show); //function (){ alert(this.arr1);} console.log(sub.say); //function (){ alert(this.arr1);} console.log(sub.show === sub2.show); //true; console.log(sub.say === sub2.say); //true;
好了,这样就把三方法的弊端干掉了,这个可以完美的使用了吧。
五、复制属性实现
拷贝我们可以写一个拷贝函数来实现。
function extend(Super,suber){ suber = suber || {}; for(var i in Super){ if(Super.hasOwnProperty(i)){ suber[i] = Super[i]; } } return suber; } var parent = { name:"dad", num:[1,2,3], say:function(){alert("dad");} } var child = { age:5, sex:"boy" }; child = extend(parent, child); //以下测试 console.log(child); /*{ age:5, sex:"boy", name:"dad", num:[1,2,3], say:function(){alert("dad");} }*/ console.log(child.say === parent.say); //true console.log(child.num === parent.num); //true
复制成功,那么child成功继承了parent的一些属性,但是后面两个测试发现他们是相等的,就表明了他们在公用同一个数组,同一个函数,函数这个可以,但是数组这个就有问题了,如果一个chiild改变了数组,几个被继承对象的数组也跟着变了,这就不给力了啊。
为什么会发生这种情况呢,js里边对象存储的是指针,然后这个指针指向这个值,我们在这复制的实际是指向该对象的指针的值,所以继承对象和被继承对象都指向了同一个对象,接下来看看如何使用深度复制来解决这个问题。
深度复制对象属性:
function extenddeep(Super, suber){ var tostr = Object.prototype.toString, astr = "[object Array]"; suber = suber || {}; for(var i in Super){ if(Super.hasOwnProperty(i)){ if(typeof Super[i] === "object"){ suber[i] = (tostr.call(Super[i]) == astr) ? [] : {}; extenddeep(Super[i],suber[i]); }else { suber[i] = Super[i]; } } } return suber; } var parent = { name:"papa", num:[1,2,3], say:function(){alert("I'm father of my son!");} } var child = { name:"jone", sex:"boy", } var kid = extenddeep(parent, child); console.log(kid); // {name: "papa" num: Array[3] say: () sex: "boy" // } console.log(kid.say === parent.say); //true console.log(kid.num === parent.num); //false console.log(kid.name); //papa
好了,深度复制完毕,但似有木有发现问题,name是parent的,也就是说如果继承对象有和被继承对象一样的属性名的属性如果不做处理就会被替换掉。那么我们可以做一下处理,先声明一个属性,保存parent里的东西,剩下的的当然就是child自己的东西了,最后再把属性给child对象就可以了。
六、利用call和apply这两个方法(借用方法)。
这个就是通过call和apply来复用其他对象的方法,达到复用的目的。
var one = { name:"object", say: function(greet){ return greet + ', ' + this.name; } } var tow = { name:"two" } one.say.call(tow, "hi"); //hi, two
这个就是借用了,好了,下课。
好吧,好吧,其实这里边还有其他东西要看。可以借用并不“带表”可以随便把某个方法赋值给谁然后跟没发生什么似的继续用。所以我们平时使用借用时要注意一下上下文,下面看下那些容易出错的地方。