开始的代码是这样的app
var Animal = function(name){ this.name = name; }; Animal.prototype.jump = function(){ console.log('jumped'); };
优势:将可共享的可重用的部分(属性或者方法)迁移到原型链上,将不可重用的部分做为对象的实例属性(属性)函数
var Human = function(name){ this.name = name; }; // 这一步会使得 // Human.prototype.constructor = Animal; // 因此须要从新手动重定向 Human.prototype = new Animal;//将父构造函数的实例对象赋值给一个子构造函数的原型 // 若是不更改 // 经过`Human`构造器构造出来的对象的构造器会变成`Animal`而不是`Human` Human.prototype.constructor = Human;(有new就要手动修改) var man = new Human('HaoyCn'); man.jump();
如今,对象 man 可使用 Animal.prototype.jump 方法,查找过程是:this
man 自身没有jump方法 查找 man.constructor.prototype,即Human.prototype,可Human.prototype自己也没有 jump 方法,而它又是一个由Animal 构造的对象,因此 查找 Animal.prototype,在其中找到了 jump 方法,执行之
建立一个实例对象,对象的prototype指向构造函数的原型(man.constructor.prototype),构造函数中的this指向这个实例对象,运行构造函数,对实例对象的属性进行赋值,返回这个实例对象spa
优势:提升了运行时的效率,没有建立新对象出来。prototype
var Human = function(name){ this.name = name; }; Human.prototype = Animal.prototype;//将一个父构造函数的原型直接赋值给子构造函数的原型 var man = new Human('HaoyCn'); man.jump();
man 自身没有jump方法
查找 man.constructor.prototype,即Human.prototype,Human.prototype是对Animal.prototype 的引用,在其中找到了 jump 方法,执行之减小了一步。
然而代价则是:对 Human.prototype 的修改都会影响到 Animal.prototype,由于前者是对后者的引用。code
一个致命缺点就是,没法修正子类构造的对象的 constructor。对象
man.constructor === man.__proto__.constructor === Human.prototype.constructor === Animal.prototype.constructor === Animal
var F = function(){};//建立要给空的函数(构造函数:中介构造器) F.prototype = Animal.prototype;//父构造函数的原型赋值给空构造函数的原型 var Human = function(name){ this.name = name; }; Human.prototype = new F;//空(父)构造函数的实例对象赋值给子构造函数的原型 Human.prototype.constructor = Human;//手动修改重定向constructor(有new就要修改) Human.prototype.sing = function(){ console.log('Mayday'); }; var man = new Human('HaoyCn'); man.jump(); man.sing();
咱们对 Human.prototype 的任何改变都变成了对一个由中介构造器建立的对象的属性的修改。jump查找过程是:继承
man 自身没有jump方法
查找 man.constructor.prototype,即Human.prototype,可Human.prototype自己也没有jump 方法,而它又是一个由 F 构造的对象,因此
查找 F.prototype,即 Animal.prototype,在其中找到了 jump 方法,执行之ip
先看“原型链继承法”中的操做: Human.prototype = new Animal; // 这将形成: // Human.prototype.name = undefined;// 没有给`Animal`传入参数之故 也就是说,Human.prototype 会多出没必要要的属性来,而中介器则避免了这种没必要要的属性。
以上继承法共通的一个缺点在于,Human 构造器构造的对象虽然能够共用 Animal.prototype,但对于name 属性而言,Human 构造器只能本身再写一遍构造 name 属性,为何不把初始化属性的方法也共(借)用呢?
构造器借用法应运而生。如今咱们把 name 属性的建立仍是交给 Animal,而后再为 Human 增长country 属性。咱们在“临时构造器法”基础上进一步完善之。原型链
var F = function(){};//建立要给空的函数(构造函数:中介构造器) F.prototype = Animal.prototype;//父构造函数的原型赋值给空构造函数的原型 //建立子构造函数 var Human = function(){ Animal.apply(this,arguments);//this.Animal(arguments):借用构造器Animal,是初始化属性的方法也共用(偷懒) this.country = arguments[1]; } Human.prototype = new F;//空(父)构造函数的实例对象赋值给子构造函数的原型 Human.prototype.constructor = Human;//手动修改重定向constructor var man = new Human('HaoyCn','China'); console.log(man.country);// China