JavaScript中的继承机制
JavaScript到底是不是面向对象的?!
有人说是,有人说基于对象更准确,因为JavaScript没有类。不去管它,但JavaScript确实提供了一些面向对象的机制。
本文主要讨论JavaScript中的继承。继承,简单来说,就是让子类获得父类的属性和方法,以达到共享和复用的目的。
在开始继承之前,首先需要创建父类。为了后续讨论的需要,我分别为父类创建了私有对象、实例对象、引用对象和两个实例方法。
创建父类的代码如下:
// 父类实例的构造函数 function Pet(name,sound){ // 私有对象 var name = "this is a pet"; // 实例对象 this.sound = "I'm a pet"; // 引用对象 this.loveFood = []; // 实例方法 this.getName = function(){ console.log(name); }; this.getLoveFood = function(){ for(var food in this.loveFood){ console.log(this.loveFood[food]); } }; } // 原型对象上的方法 Pet.prototype.voice = function(){ console.log(this.sound); }
接下来,我们来看在JavaScript中几种能完成继承的手段,他们分别是new方式、extend方式、clone方式和mixin方式。
(1)new方式
// 子类构造函数 function Dog(sound){ if(sound){ this.sound = sound; } } // 使子类构造函数的原型对象指向父类的一个实例 Dog.prototype = new Pet; // 调整子类构造函数的原型对象的constructor指向 Dog.prototype.constructor = Dog; var dog1 = new Dog("wangwang"); console.log(dog1.sound);//wangwang dog1.getName();//this is a pet dog1.voice();//wangwang dog1.loveFood.push("pork"); dog1.getLoveFood();//pork console.log("dog2"); var dog2 = new Dog(); dog2.voice();//I'm a pet dog2.getLoveFood();//pork console.log(dog1 instanceof Dog);//true console.log(dog1 instanceof Pet);//true
(2)extend方式
function extend(b,p){ var F= function(){}; F.prototype = p.prototype; b.prototype = new F(); b.prototype.constructor = b; b.su = p.prototype; } // 子类构造函数 function Dog(sound){ if(sound){ this.sound = sound; } } extend(Dog,Pet); var dog1 = new Dog("wangwang"); console.log(dog1.sound); // 报错 // dog1.getName(); dog1.voice(); // 报错 // dog1.loveFood.push("pork"); dog1.getLoveFood(); console.log("dog2"); var dog2 = new Dog(); // 报错 // dog2.getName(); dog2.voice(); dog2.getLoveFood();
(3)clone方式
function clone(o){ function F(){}; F.prototype = o; return new F; } var Dog={ name:"this is a dog", sound:"wangwang", loveFood:[], voice:function(){console.log(this.sound);}, getLoveFood:function(){ for(var food in this.loveFood){ console.log(this.loveFood[food]); } } }; var jwawa = clone(Dog); jwawa.voice(); jwawa.name = "jjjj"; jwawa.loveFood.push("meat"); console.log("Dog.name = "+Dog.name); console.log("jwawa.name = "+jwawa.name); // meat jwawa.getLoveFood(); var shapi = clone(Dog); console.log("shapi.name = "+shapi.name); // meat shapi.getLoveFood();
(4)mixin方式
var Mixin = function(){}; Mixin.prototype ={ serialize:function(){ var output =[]; for(key in this){ output.push(key + ':' + this[key]); } return output.join(','); } }; function augment(receivingClass,givingClass){ if(arguments[2]){ for (var i = arguments.length - 1; i >= 0; i--) { receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; }; }else{ for(methodName in givingClass.prototype){ if(!receivingClass.prototype[methodName]){ receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } } function Book(){ this.name = "123"; this.price = 456; this.year = "2015"; } Book.prototype.show = function(){console.log("show");}; augment(Book,Mixin); var book = new Book; console.log(book.serialize()); // 输出 // name:123,price:456,year:2015,show:function (){console.log("show");},serialize:function (){ // var output =[]; // for(key in this){ // output.push(key + ':' + this[key]); // } // return output.join(','); // }