首先回顾一下原型式继承:javascript
function object(obj){ function F(){} f.prototype = obj; return new F(); }
寄生式继承是与原型式继承紧密相关的一种思路,而且一样也是由克罗克福德推而广之的。java
说到寄生式继承不得不说工厂模式和寄生构造函数模式建立对象。下面来回顾一下工厂模式建立对象:函数
function createPerson(name, age, job){ let o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ console.log(this.name); } return o; } let p = createPerson('bob', 18, 'JavaScript'); p.sayName();//bob
在函数体内建立了一个对象,而后对这个对象进行加强,添加一些属性和方法,再返回这个对象,使用时直接调用createPerson
,并将参数传给它,就获得了咱们想要的对象,但本质上 createPerson
不过是封装了用于加强o
的代码。this
再看寄生构造函数模式建立对象:.net
function Person(name, age, job){ let o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ console.log(this.name); } return o; } let p = new Person('bob', 18, 'JavaScript'); p.sayName();//bob
思路其实和工厂模式同样,只不过建立对象是经过new关键字进行的,而工厂模式是直接调用。prototype
寄生式继承的思路就是相似上面这样:建立一个用于封装继承过程的函数,该函数内部以某种方式来加强对象,而后返回这个对象,该对象就是原对象的一个子对象。来看下面的示例:code
function extend(obj){ let child = object(obj);//或者使用Object.create(obj); child.sayHi = function(){ console.log('hi'); } return child; }
建立extend
函数,接收的参数就是将要继承的对象。函数体内使用object
函数返回了obj
的子对象child
,而后经过给child
添加sayHi
方法,对child
进行了加强,最后返回child
。与原型式继承相比,寄生式继承帮咱们封装了加强的代码,而原型式继承须要咱们手动书写加强的代码。来看下面的示例:对象
let p = { name: 'bob', friends: ['jack', 'rose'] } //使用寄生式继承 let p2 = extend(p); p2.sayHi();//hi //使用原型式继承 let p3 = object(p); p3.sayHi = function(){ console.log('hi'); } p3.sayHi();//hi
在JavaScript继承(四)——原型式继承中提到的Object.create
方法,其能够接受一个或两个参数,接收一个参数时等同于object函数,也就是原型式继承,其实接收两个参数就等同于寄生式继承。来看下面的示例:blog
let p4 = Object.create(p, { sayHi: { value: function(){ console.log('hi'); } } }); p4.sayHi();//hi
因此不管是原型式继承仍是寄生式继承,使用Object.create
就够了。继承
实际上,寄生式继承基本上能够替代原型式继承,寄生式继承能够看做原型式继承的加强。须要注意的是使用寄生式继承来为对象添加函数,会因为不能作到函数复用而下降效率,这一点与构造函数模式相似。关于构造函数模式,以下所示:
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } let p1 = new Person('zhangsan', 18, 'JavaScript'); let p2 = new Person('lisi', 20, 'Java');
能够参考这篇文章--JavaScript建立对象(二)——构造函数模式。