上一篇介绍了对象建立的几种基本方式,今天咱们看分析下对象的继承。javascript
function Obj1() { this.name1 = "张三"; } function Obj2() { } Obj2.prototype = new Obj1(); var t2 = new Obj2(); alert(t2.name1);
这里有个明显的缺点就是:(若是父类的属性是引用类型,那么咱们在对象实例修改属性的时候会把原型中的属性修改,这样会在每一个实例对象中改变数据,而这不是咱们想要的效果)html
function Obj1() { this.arr = ["张三"]; } function Obj2() { } Obj2.prototype = new Obj1(); var t2 = new Obj2(); alert(t2.arr);//打印“张三” t2.arr[t2.arr.length] = "李四"; var t1 = new Obj2(); alert(t1.arr);//打印“张三,李四”
例:java
函数
那咱们怎样规避这种问题呢?接着往下看。学习
function Obj1() { this.arr = ["张三"]; } function Obj2() { Obj1.call(this);//【1.新增】 } //Obj2.prototype = new Obj1();【2.注释这行】 var t2 = new Obj2(); alert(t2.arr);//打印“张三” t2.arr[t2.arr.length] = "李四"; var t1 = new Obj2(); alert(t1.arr);//打印“张三,李四”
咱们看到上面代码,就注释了一行,新增了之后。打印出来的效果彻底不同了。如今的arr属性是每一个实例对象独有的了。(以前是定义到原型上的,而原型的属性对每一个实例都是共享的)this
例:spa
.net
一样,单纯的这种方式也是有问题的。由于咱们这样就没法继承对象的方法了。如:prototype
function Obj1() { this.arr = ["张三"]; } Obj1.prototype.sayHi = function () { alert(this.arr); }////【1.新增】 function Obj2() { Obj1.call(this); } var t2 = new Obj2(); //t2里面是没有sayHi方法的
咱们可使用原型和构造的混用来解决,以下:code
function Obj1() { this.arr = ["张三"]; } Obj1.prototype.sayHi = function () { alert(this.arr); } function Obj2() { Obj1.call(this); } Obj2.prototype = new Obj1();//【1.新增】 var t2 = new Obj2(); t2.sayHi();
如上,经过构造函数中的 Obj1.call(this); 和设置原型属性 Obj2.prototype = new Obj1(); 结合使用,完美解决问题。
这里须要注意一个地方,若是把 Obj2.prototype = new Obj1(); 改为 Obj2.prototype = Obj1.prototype ; 的话,会有你想不到的问题。如:
function Obj1() { this.arr = ["张三"]; } Obj1.prototype.sayHi = function () { alert(this.arr); } function Obj2() { Obj1.call(this); } Obj2.prototype = Obj1.prototype;//【1.新增】 var t2 = new Obj2(); t2.constructor.prototype.sayHi = function () { alert("test") };//修改Obj2中的原型的方法 var t1 = new Obj1(); t1.sayHi(); //影响到了Obj1中的原型的方法。由于 Obj2.prototype = Obj1.prototype;让两个对象的原型指向了同一处。 //因此仍是只能用Obj2.prototype = new Obj1();
例:
如:
//*************Obj1**** function Obj1() { this.arr = ["张三"]; } Obj1.prototype.sayHi = function () { alert(this.arr); } //*************Obj2**** function Obj2() { Obj1.call(this); this.name = "张三"; } Obj2.prototype = new Obj1(); Obj2.prototype.sayHi2 = function () { alert(this.name); }; //*************Obj3**** function Obj3() { Obj2.call(this); } Obj3.prototype = new Obj2(); Obj3.prototype.sayHi3 = function () { }; //******************* var t3 = new Obj3(); t3.sayHi();
Obj3继承Obj2,Obj2继承Obj1。咱们的Obj3的实例对象访问sayHi的时候,会先去Obj3的实例对象中找sayHi方法(没找到),而后去Obj3的原型中找(没找到),而后去父类Obj2的原型中找(没找到),而后去Obj1的原型中找(找到了)。这个找的路径就是原型链。
(补充分割线20151230)
以上,咱们在说继承的时候,咱们都是 obj2.prototype = new obj1(); 原型指向父类构造函数。其实这样有一个问题。如:
function obj1() { this.name2 = "张三"; } obj1.prototype.sayhi = function () { alert(this.name2); } function obj2() { obj1.call(this);//继承属性 } obj2.prototype = new obj1(); var obj = new obj2();
咱们看到name2这个属性,并非咱们想要在prototype中的prototype.name2中继承过来的。(感受不是那么干净)
然而,咱们能够:
function obj1() { this.name2 = "张三"; } obj1.prototype.sayhi = function () { alert(this.name2); } function obj2() { obj1.call(this);//继承属性 } //obj2.prototype = new obj1(); obj2.prototype = Object.create(obj1.prototype);//继承原型中的方法【E5中才有的一种新的对象建立方式】 var obj = new obj2();
这是学习记录,不是教程。文中错误不免,您能够指出错误,但请不要言辞刻薄。
原文连接:http://haojima.net/zhaopei/517.html
本文已同步至目录索引:一步步学习javascript
欢迎上海“程序猿/媛”、"攻城狮"入群:【沪猿】229082941 入群须知
欢迎对我的博客感兴趣的道友加入群:【嗨-博客】469075305 入群须知
若是您以为文章对您有那么一点点帮助,那么麻烦您轻轻的点个赞,以资鼓励。