javascript设计模式【02】继承
原型对象与prototype属性的区别
- 每个对象都有原型对象
- 只有函数才有prototype属性,当函数作为构造函数调用时,其prototype属性作为创建的对象的原型对象
实现继承的常用方法:
1 类继承:extend函数,将父类从子类构造函数中解耦,父类构造函数只要能恰当处理适当参数即可,通过superclass可以在需要重新定义父类方法是访问父类中的实现方法
-
1 function extend (subClass, superClass) { 2 var F = function () {}; 3 F.prototype = superClass.prototype; 4 subClass.prototype = new F(); 5 subClass.prototype.constructor = subClass; 6 7 subClass.superclass = superClass.prototype; // 为子类定义静态属性,指明父类,实现解耦 8 if (superClass.prototype.constructor === Object.prototype.constructor) { 9 superClass.prototype.constructor = superClass; 10 } // end if 11 } // end extend() 12 13 function Person (name) { 14 this.name = name; 15 } // end Person() 16 Person.prototype.getName = function () { 17 return this.name; 18 }; // end getName() 19 20 function Author (name, books) { 21 Author.superclass.constructor.call(this, name); // 此时只要父类构造函数接受并正确处理name即可 22 this.books = books; 23 } // end Author() 24 25 extend(Author, Person); 26 27 Author.prototype.getBooks = function () { 28 return this.books; 29 }; // end getBooks() 30 Author.prototype.getName = function () { 31 // 通过superclass可以在需要重新定义父类方法是访问父类中的实现方法 32 var name = Author.superclass.getName.call(this); 33 return name + " , author of " + this.getBooks(); 34 }; // end getName() 35 36 var a = new Author("xxx", "xxx"); 37 console.log(a.getName()); // xxx , author of xxx
2 原型继承:通过clone创建子类。子类对象读写的不对等性:子类在为父类同名属性赋值之前引用的是父类属性,进行赋值时创建自己的属性,当父类包含引用类型时,如array.push()和object写操作。将影响父类,此时如果其他子类没有定义自己的对应属性,将会受到影响。
1 function clone(obj) { 2 function F () {}; 3 F.prototype = obj; 4 return new F; 5 } // end clone() 6 7 var o = { 8 name: "xxx", 9 books: ["javascript"], 10 getName: function () { 11 return this.name; 12 } 13 }; 14 15 var b = clone(o); 16 console.log(b.getName()); // xxx 17 console.log(b.books); // ["javascript"] 18 19 var c = clone(o); 20 console.log(c.hasOwnProperty("name")); // false 21 c.name = "ccc"; 22 console.log(c.hasOwnProperty("name")); // true 23 console.log(c.name); // ccc 24 c.books.push("java"); 25 26 console.log(b.getName()); // xxx 27 console.log(b.books); // ["javascript", "java"]
3 掺元类继承:将方法扩充的方式让类具有某个方法
1 var Mixin = function () {}; 2 Mixin.prototype = { 3 serialize: function () { 4 var output = []; 5 for (key in this) { 6 output.push(key + ": " + this[key]); 7 } // end for 8 return output.join(", "); 9 } // end serialize() 10 }; // end prototype 11 12 function augment(receivingclass, givingClass) { 13 for (key in givingClass.prototype) { 14 if (!receivingClass.prototype[key]) { 15 receivingClass.prototype[key] = givingClass.prototype[key]; 16 } // end if 17 } // end for 18 } // end augment() 19 20 augment(Author, Mixin); 21 var author = new Author("xxx", "xxx"); 22 var serializedString = author.serialize();
三种方式都可以实现继承。类式继承法与其他编程语言相似,容易理解。但是系统开销相对大。原型式继承为javascript所特有。简洁高效。掺元法类似接口实现。也不错,掺元法在提供通用方法时比较恰当。