javascript继承的我的总结

开始的代码是这样的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 方法,执行之

clipboard.png

建立一个实例对象,对象的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。对象

clipboard.png

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

clipboard.png

先看“原型链继承法”中的操做:
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

clipboard.png

相关文章
相关标签/搜索