浅谈js对象的创建和对6种继承模式的理解和遐想


Posted in Javascript onOctober 16, 2016

JS中总共有六种继承模式,包括原型链、借用构造函数、组合继承、原型式继承寄生式继承和寄生组合式继承。为了便于理解记忆,我遐想了一个过程,对6中模式进行了简单的阐述。

很长的一个故事,姑且起个名字叫女娲造人吧。

创建对象

女娲一个一个的捏人(创建对象),这样太慢,于是设计了一种机器(函数),想造什么样的,告诉他这个人有哪些特点和功能,机器来制造。这就是工厂模式的(使用同一个接口创建对象,回产生大量重复代码,由此发明了一种函数(模具))。

但是机器造人同样也比较麻烦(挖土、和泥、捏眼睛、捏鼻子...)于是封装的思想来了,鼻子眼睛什么的提前捏好备用,改造机器,告诉要造的人具有什么样的眼睛,鼻子,机器可以直接拿来安装ok,这样的机器就是构造函数。

这样仍然存在问题,假设要让捏的人都能跑,就要机器给每个人安装一个‘跑'的功能,这样工序太慢,还可能出错,找第三方吧(函数方法定义到构造函数外部,全局作用域中)。第三方负责给我把捏的人都装上跑的功能,我拿来再放到机器上用,省的每次都加工。ok,人都能跑了,很方便,但是问题又出现了,造的人还需要‘跳'、‘走'..的N个功能,总不能再找N个第三方吧,那这样建机器就没意义了。于是女娲(开发人员)早创造了原型模式...厉害了我的娲。

原型模式中每个函数都有一个prototype属性,是指针,指向原型对象。原型对象包含能让所有实例共享的属性和方法,这个原型对象有一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。

看似有点绕,从女娲这个角度就好理解了:造物主女娲娘娘还发明了个各种各样的模具(原型对象),要开始造了:1造一类人-->用的是造这类人的模具。毕竟可以造万物,造什么用什么样的模具。所有造人机器(函数)都有各自唯一的一个模具(原型对象),并且机器有一个标签[prototype],指向模具,这个模具有能贴生产标志的[constructor]属性,指向这个机器,表示是这个机器的模具生产。因此要造什么样的一类人,只需要改模具就好了。这就是原型对象的好处,方便,快捷。

生产过程如下:

1造机器A :function  jqA(){}; //有个prototype属性,指向模具(原型对象)

2造模具:jqA.prototype={

constructor: jqA, //相当于贴上标签,由A机器生产,

name:'lily',

skin:'white',

run: function(){

alert(this.name+'run');

}

 这个模具负责造名字叫lili,皮肤为white,能run的这类人。

3  造一个这类型的人    var person1=new jqA();

再造一个这类型的人  var person2=new jaA();

person1和person2都有一个[[prototype]]属性,表示经过模板A处理了,指向A模板

很完美,问题又来了,这样生产出来的人都一样,迎面走来五个一模一样的白皮肤窈窕美女,然后又有五个一抹一样的矮挫丑,太可怕了。 所以机器A在用模板的同时,还可以根据女指令来使造的这类人有不同的特点,比如:这个蓝眼睛,那个胖点。。这个额外的功能通过构造函数实现---》组合使用构造函数和原型模式

生产过程如下:

//组合使用构造函数模式和原型模式

function Person(name,skill,country) {

  this.name=name;

  this.age=skill;

  this.country=country;

  this.member=["刘封","刘婵"];

} //机器可以听命令

 

Person.prototype={

  constructor:Person,

  sayName:function () {

    alert(this.name);

  }

} //还可以用模板

 var person1=new Person('马超','铁骑','蜀国');

 var person2=new Person('刘备','仁德','蜀国');

这时候,女娲懒得照顾机器的同时又照顾模板,所以直接把模板装在了机器中:在构造函数中初始化原型对象---》动态原型模式  更方便了

生产过程如下:

function Person(name,skill,country) {

  this.name=name;

 
  this.skill=skill;

  
this.country=country;

 if(typeof this.sayCountry !=undefined){

  
 Person.prototype.sayCountry=function () {

   
  alert(this.country);

 
  };

     
  }

    
   }

var friend=new Person('张飞','咆哮','蜀国');

friend.sayCountry();

还有问题?ok,提供寄生构造函数模式:机器中加个内部机器,这个内部机器负责生产,并生产的的人提供给外部机器,外部机器向外提供这类人就好。(一般用不到吧..)

继承(我的理解—_—)

问题:女娲要造另一批人B,这批人的模板B造好了,但是想让这批人有之前造过的那批人的特点,怎么办?先让这些人过滤一下先前的模板A,在放到B中造就ok,这样类‘B人'就继承了‘A'类人的特点。如何过滤:父实例=子原型  建B的模板,造一个a出来,这个a肯定要过滤A模板,所以让B的模板等于a就ok,问题解决。 

//父函数,机器A,A类人。它的实例a中有[[Prototype]]属性和自定义的property属性

function SuperType(){

this.property=true;

}

//在SuperType原型对象(模具A)中添加getSuperValue方法

SuperType.prototype.getSuperValue=function(){

return this.property 

}

//子函数,机器B,B类人。构造函数SubType,它的实例中有[[Prototype]]属性和自定义的subproperty属性

function SubType(){

this.subproperty=false;

}

//继承了SuperType (原型链)

SubType.prototype=new SuperType(); //机器B=a

//在SubType原型对象(模具B)中添加getSubValue方法

SubType.prototype.getSubValue=function(){

return tis.subproperty;

};

var insatance=new SubType();

alert(insatance.getSuperValue()); //true

问题:引用类型值会改变,因为实例共享属性,和原型模式中的问题相同

解决方案:经典继承 (借用构造函数):其实就是把模具A设计到机器B中,但是它已经不是模板了,机器B会给生产的b们添加这些A中的属性和方法,但是可以人为控制,女娲又命令机器B根据传递不同的命令生产不同的b。

在子类构造函数的内部调用超类构造函数

相当于把父类的属性实例化到子类中?Java中的super() 存在疑问

function SuperType(){

this.colors=['red','blue','green'];
}

function SubType(){

//继承了SuperTYpe

SuperType.call(this);

}

var insatance1=new SubType();

insatance1.colors.push('black');

alert(insatance1.colors);// 'red,blue,green,black'

 

var insatance2=new SubType();

alert(insatance2.colors);//'red,blue,green'

1传递参数:

借用构造参数可以在子类型构造参数中向超类型构造参数传递参数

function SuperType(name){

  this.name=name;

}

function SubType(){

//继承了SuperTYpe,同时还传递了参数

SuperType.call(this,'赵云');

//实例属性

this.age=29;

}

var insatance=new SubType();

alert(insatance.name); //赵云

alert(insatance.age); //29

为了确保SuperType构造函数不会重写子类型的属性,可以在调用超类型构造函数之后,再添加应该在子类型中定义的属性。

问题:浪费劳动力,在机器中创建A具有的功能和属性,那么A模板就没用了,相当于回到工厂模式,都有打火机了,还要钻木取火吗....

解决方案:组合继承  

在公司加班没事做,现在赶着下班,故事编不下去了,后面的继承模式搬之前的记录吧..

 

原型链和构造函数技术组合到一起,使用原型链实现对原型属性和方法的继承,借用构造函数来实现对实例属性的继承。这样通过在原型上定义方法实现了函数的复用,有能够保证每个实例都有它自己的属性

原型继承:方法可以,实例属性无法继承; 借用构造函数:实例属性可以,方法不行。 一起用,完美。

function SuperType(name){

 this.name=name;


 thi.colors=['red','blue','green'];


   }



SuperType.prototype.sayName=function(){

   alert(this.name);



};

 



function SubType(name,age){


//继承属性


SuperType.call(this,name);


this.age=age;



}



 //继承方法

 
SubType.prototype=new SuperType();

 

 
SubType.prototype.sayAge=function(){

 
alert(this.age);


 }

 


var instance1=new SubType('zhaoyun',29);


instance1.colors.push('black');


alert(instance1.colors); //'red,blue,green,black'


instance1.sayName();//zhaoyun


instance1.sayAge();//29

 


var insatance2=new SubType('诸葛瑾',25);


alert(instance2.colrs);'red,blue,green'


instance22.sayName();//诸葛瑾


instance2.sayAge();//25

以上就是小编为大家带来的浅谈js对象的创建和对6种继承模式的理解和遐想全部内容了,希望大家多多支持三水点靠木~

Javascript 相关文章推荐
javascript instanceof 与typeof使用说明
Jan 11 Javascript
js escape,unescape解决中文乱码问题的方法
May 26 Javascript
JavaScript之Getters和Setters 平台支持等详细介绍
Dec 07 Javascript
兼容ie、firefox的图片自动缩放的css跟js代码分享
Aug 12 Javascript
JavaScript数值转换的三种方式总结
Jul 31 Javascript
用canvas 实现个图片三角化(LOW POLY)效果
Feb 18 Javascript
js转html实体的方法
Sep 27 Javascript
js制作支付倒计时页面
Oct 21 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
Jul 03 Javascript
ionic2.0双击返回键退出应用
Sep 17 Javascript
js验证密码强度解析
Mar 18 Javascript
React Ant Design树形表格的复杂增删改操作
Nov 02 Javascript
利用jQuery对无序列表排序的简单方法
Oct 16 #Javascript
JS实现动态增加和删除li标签行的实例代码
Oct 16 #Javascript
js利用appendChild对标签进行排序的实现方法
Oct 16 #Javascript
浅谈js控制li标签排序问题 js调用php函数的方法
Oct 16 #Javascript
JS实现禁止鼠标右键的功能
Oct 15 #Javascript
Vue.js快速入门实例教程
Oct 15 #Javascript
JavaScript随机生成颜色的方法
Oct 15 #Javascript
You might like
PHP伪造referer实例代码
2008/09/20 PHP
用PHP实现递归循环每一个目录
2010/08/08 PHP
分享十款最出色的PHP安全开发库中文详细介绍
2015/03/22 PHP
PHP实现随机生成水印图片功能
2017/03/22 PHP
有效的捕获JavaScript焦点的方法小结
2009/10/08 Javascript
javascript操作css属性
2013/12/30 Javascript
Windows 系统下安装和部署Egret的开发环境
2014/07/31 Javascript
不使用ajax实现无刷新提交表单
2014/12/21 Javascript
使用jquery实现仿百度自动补全特效
2015/07/23 Javascript
javascript去掉代码里面的注释
2015/07/24 Javascript
使用BootStrapValidator完成前端输入验证
2016/09/28 Javascript
Node.js中的http请求客户端示例(request client)
2017/05/04 Javascript
Mobile Web开发基础之四--处理手机设备的横竖屏问题
2017/08/11 Javascript
React-Native使用Mobx实现购物车功能
2017/09/14 Javascript
使用async、enterproxy控制并发数量的方法详解
2018/01/02 Javascript
详解javascript appendChild()的完整功能
2018/08/18 Javascript
手动实现vue2.0的双向数据绑定原理详解
2021/02/06 Vue.js
[41:20]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS DK
2014/05/26 DOTA
django自定义Field实现一个字段存储以逗号分隔的字符串
2014/04/27 Python
Python的ORM框架SQLAlchemy入门教程
2014/04/28 Python
从零学Python之入门(五)缩进和选择
2014/05/27 Python
Python切片用法实例教程
2014/09/08 Python
Python开发微信公众平台的方法详解【基于weixin-knife】
2017/07/08 Python
python2.7实现爬虫网页数据
2018/05/25 Python
keras tensorflow 实现在python下多进程运行
2020/02/06 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
纯css3实现走马灯效果
2014/12/26 HTML / CSS
5 个强大的HTML5 API 函数推荐
2014/11/19 HTML / CSS
世界领先的以旅馆为主的在线预订平台:Hostelworld
2016/10/09 全球购物
深圳茁壮笔试题
2015/05/28 面试题
英语硕士生求职简历的自我评价
2013/10/15 职场文书
英语系本科生求职信范文
2013/12/18 职场文书
我的大学生活职业生涯规划
2014/01/02 职场文书
工作证明英文模板
2014/10/21 职场文书
长城导游词300字
2015/01/30 职场文书
党小组推荐意见
2015/06/02 职场文书