总结 构造函数与非构造函数 原型继承的一个方法

这两天真的一直在看原型以及继承之间的千丝万缕,哇,收获颇多,不过所谓温故知新,还是要多复习复习知识点,才能察觉那些之前不易发现的小小sparkle

真心推荐MDN文档——对象原型JavaScript 中的继承,文档指出了很多原理性的东西,所谓饮水思源,大家千万不要轻易就相信别人说什么好哇就像挖到宝藏一样,要多实践,多探索原理性的东西你才能真正把它掌握,它才真的是你的东西。

期间我还参考了阮一峰老师的Javascript 面向对象编程(一):封装Javascript面向对象编程(二):构造函数的继承

Javascript面向对象编程(三):非构造函数的继承

廖雪峰老师的原型继承

在MDN文档以及廖雪峰老师那里都提到了构造函数继承的一种方法:(这里主要说明继承的一个办法,原理性的说明请看以上推荐链接)

function Person(first, last, age, gender, interests) {
  this.name = {
    first,
    last
  };
  this.age = age;
  this.gender = gender;
  this.interests = interests;
};

Person.prototype.greeting = function() {
  alert('Hi! I\'m ' + this.name.first + '.');
};

这里先说明一下,在构造函数中,属性最好都写在构造函数里,而方法最后都写在prototype(原型对象)里,这样层次比较分明,但是如果是常属性(值不变),那么他可以写进prototype里,这样可以减少内存的占据

我们现在要创建一个Teacher类,需要继承Person的所有属性和方法,

同时也包括:

一个新的属性subject——这个属性包含了教师教授的学科。

一个被更新的greeting()方法,这个方法打招呼听起来比一般的greeting()方法更正式一点——对于一个教授一些学生的老师来说。

MDN文档的做法是:

function Teacher(first, last, age, gender, interests, subject) {
 
// 调用person构造函数,绑定this变量:
 Person.call(this, first, last, age, gender, interests); 
  this.subject = subject;
}

Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;



 而这里廖雪峰老师的做法的第一步也是(与廖老师文章里例子不同但原理相似)

 Person.call(this, first, last, age, gender, interests); 
  this.subject = subject;

之后他指出,调用了Person构造函数不等于继承了Person,Teacher创建的对象的原型是:

new Teacher() ----> Teacher.prototype ----> Object.prototype ----> null

必须想办法把原型链修改为:

new Teacher() ----> Teacher.prototype ----> Person.prototype ----> Object.prototype ----> null

我们必须借助一个中间对象来实现正确的原型链,这个中间对象的原型要指向Person.prototype。为了实现这一点,参考道爷(就是发明JSON的那个道格拉斯)的代码,中间对象可以用一个空函数F来实现: 

// 空函数F:
function F() {
}

// 把F的原型指向Student.prototype:
F.prototype = Person.prototype;

// 把Teacher的原型指向一个新的F对象,F对象的原型正好指向Person.prototype:
Teacher.prototype = new F();

// 把PrimaryStudent原型的构造函数修复为Teacher:
Teacher.prototype.constructor = Teacher;

 

重写Teacher的greeting函数: 

Teacher.prototype.greeting = function() {
  var prefix;

  if(this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') {
    prefix = 'Mr.';
  } else if(this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') {
    prefix = 'Mrs.';
  } else {
    prefix = 'Mx.';
  }

  alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.');
};

验证: 

var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');

teacher1.name.first;
teacher1.interests[0];
teacher1.bio();
teacher1.subject;
teacher1.greeting();

 廖老师用空函数的方法实现了间接继承又不占用多少空间,Teacher.prototype的改写也不会影响上一级的prototype,妙也!

但是为什么MDN文档用

Teacher.prototype = Object.create(Person.prototype);

就基本全搞定继承了呢?

带着好奇我查了这个函数的原理

 Object.create =  function (o) {
      var F = function () {};
      F.prototype = o;
      return new F();
  };

哈哈哈哈,这不是跟廖老师的方法一样嘛,也是造一个空函数,然后间接实现函数的继承!

 

而非构造函数中,阮老师总结的第一个方法 object()方法,其原理类似于Object.create()

function object(o) {

    function F() {}

    F.prototype = o;

    return new F();

  }

 

 var Chinese = {
      nation:'China',
      greeting:function (name) {
          alert('Hi! I\'m ' + name+' from '+this.nation+ '.');
      }
  };
  var Doctor =Object.create(Chinese);
  Doctor.career='doctor';
  Doctor.greeting=function(name){
      alert('Hi! I\'m a ' + this.career+' from '+this.nation+ ',my name is '+name+ ' .');
  };
  alert(Doctor.nation);//China
  Doctor.greeting('Emma');//Hi! I'm a doctor from China,my name is Emma .

大家可以试试看。 

好的,总结到此啦,阮一峰老师提到了很多构造函数的继承方法,但是各有利弊吧,原型以及继承这块‘深海‘’还是需要我们多去翻滚才行,这里顺便抛一个new方法原理,自己好好瞎捉摸吧哈哈哈哈

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值