浅谈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 相关文章推荐
学习ExtJS table布局
Oct 08 Javascript
Javascript绝句欣赏 一些经典的js代码
Feb 22 Javascript
Jquery实现网页跳转或用命令打开指定网页的解决方法
Jul 09 Javascript
jquery获取div距离窗口和父级dv的距离示例
Oct 10 Javascript
JavaScript DOM节点添加示例
Jul 16 Javascript
JavaScript实现选择框按比例拖拉缩放的方法
Aug 04 Javascript
Ext JS框架中日期函数的用法及日期选择控件的实现
May 21 Javascript
详解Vue2 无限级分类(添加,删除,修改)
Mar 07 Javascript
js实现瀑布流效果(自动生成新的内容)
Mar 16 Javascript
微信小程序实现锚点功能
Nov 20 Javascript
node.js中事件触发器events的使用方法实例分析
Nov 23 Javascript
JavaScript代码实现简单计算器
Dec 27 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 的异常处理、错误的抛出及回调函数等面向对象的错误处理方法
2012/12/07 PHP
PHP设计模式之命令模式的深入解析
2013/06/13 PHP
PHP实现下载断点续传的方法
2014/11/12 PHP
php array_reverse 以相反的顺序返回数组实例代码
2017/04/11 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
网站导致浏览器崩溃的原因总结(多款浏览器) 推荐
2010/04/15 Javascript
js URL参数的拼接方法比较
2012/02/15 Javascript
JS获取地址栏参数的小例子
2013/08/23 Javascript
iframe的onreadystatechange事件在firefox下的使用
2014/04/16 Javascript
jquery+ajax请求且带返回值的代码
2015/08/12 Javascript
jQuery Mobile和HTML5开发App推广注册页
2016/11/07 Javascript
AngularJS 表单验证手机号的实例(非必填)
2017/11/12 Javascript
解决angularjs前后端分离调用接口传递中文时中文乱码的问题
2018/08/13 Javascript
vue动态改变背景图片demo分享
2018/09/13 Javascript
利用原生的JavaScript实现简单拼图游戏
2018/11/18 Javascript
js实现一款简单踩白块小游戏(曾经很火)
2019/12/02 Javascript
js实现点击选项置顶动画效果
2020/08/25 Javascript
[54:19]完美世界DOTA2联赛PWL S2 Magma vs PXG 第二场 11.28
2020/12/01 DOTA
python 转换 Javascript %u 字符串为python unicode的代码
2016/09/06 Python
Python中创建字典的几种方法总结(推荐)
2017/04/27 Python
python遍历序列enumerate函数浅析
2017/10/17 Python
Django 连接sql server数据库的方法
2018/06/30 Python
将tensorflow的ckpt模型存储为npy的实例
2018/07/09 Python
Python面向对象之继承和组合用法实例分析
2018/08/27 Python
python读写配置文件操作示例
2019/07/03 Python
Python打开文件、文件读写操作、with方式、文件常用函数实例分析
2020/01/07 Python
解决TensorFlow训练内存不断增长,进程被杀死问题
2020/02/05 Python
python 在sql语句中使用%s,%d,%f说明
2020/06/06 Python
Keras 切换后端方式(Theano和TensorFlow)
2020/06/19 Python
python 如何读、写、解析CSV文件
2021/03/03 Python
萨克斯第五大道精品百货店: Saks Fifth Avenue
2017/04/28 全球购物
老教师工作总结的自我评价
2013/09/27 职场文书
大学生饮食连锁店创业计划书
2014/01/17 职场文书
说明书怎么写
2014/05/06 职场文书
会计试用期工作总结2015
2015/05/28 职场文书
经典祝酒词大全
2015/08/12 职场文书