JS常见构造模式实例对比分析


Posted in Javascript onAugust 27, 2018

本文实例分析了JS常见构造模式。分享给大家供大家参考,具体如下:

1.工厂模式

没有解决对象识别的问题。因为函数内部使用了new Object来创建对象

function Factory(name,age)
{
  var o=new Object();
  o.name=name;
  o.age=age;
  o.what=what;//用函数引用的方式消除重复创建相同函数的弊端,节省资源.函数引用可以修改this的指向,函数调用不可以!
  return o;
}
what=funciton()
{
  alert(this.name+this.age);
}
var o=Factory("12",12);
o.what();//what中的this指向o对象

这时候的constructor是Object,同时所有通过工厂模式返回的对象都是Object类型,所以instanceof操作符没有意义

console.log(o.constructor);
//打印function Object() { [native code] }
console.log(o instanceof Object);
//而且这时候所有的对象都是Object类型的

2.构造函数模式

function Person(name,age)
{
this.name=name;
this.age=age;
this.sayName=function(){ alert(this.name);}//相当于this.sayName=new Function("alert(this.name)")
}
var p1=new Person("xx",12);
var p2=new Person("yy",13);
alert(p1.sayName==p2.sayName)//内存地址不一样!返回false

构造函数相比工厂模式的优点在于能够正确的返回对象的类型,instanceof返回正确的结果。缺点在于如果向上面那样,那么在每一个对象上面都要有一个sayName方法,而且这些sayName方法不是同一个Function实例,因为ECMAScript中函数是对象,因此每定义一个函数,也就是实例化了一个对象!

对上面的方法进行优化:

function Person(name,age)
{
this.name=name;
this.age=age;
this.sayName=sayName;//函数引用的方法,共享了同一个sayName,p1,p2的内存地址一样,p1.sayName==p2.sayName返回true
}
function sayName()
{
alert(this.name);
}

缺点:全局函数sayName只能被某个对象调用p1.sayName,让全局函数名不副实;如果对象要定义很多方法,那么就要定义很多的全局函数,所以自定义的引用类型没有封装性可言

3.原型模式

(1)无法通过构造函数参数向原型属性动态传值,后果就是:没有个性,改变原型属性的值,所有的实例都会受到干扰!

(2)当原型属性的是引用类型的时候,如果在一个对象实例上修改属性,将会影响所有实例!

总之一句话:牵一发而动全身(包括属性和引用类型的值)是原型模式的特点。但是相比于构造函数类型,原型类型满足

person1.sayName===person2.sayName//两者的引用是一样的

4.构造函数原型模式

用构造函数定义个性,用原型模式定义共性

function Person(name,age)
{
 this.name=name;
 this.age=age;
 this.friends=['liangklfang','qinliang'];
}
//用原型定义共性
Person.prototype={
 constructor:Person,
 sayName:function()
 {
  console.log(this.name);
 }
}
var person1=new Person('liangklfang',"12");
var person2=new Person('liangklf',"14");
console.log(person1.sayName===person2.sayName);
//共性是函数,打印true
console.log(person1.friends===person2.friends);
//friends是个性,打印false

也可以对构造函数原型模式进行优化,就是常说的动态原型模式

function Book(title,page)
{
 this.title=title;
 this.page=page;
 if(typeof Book.isLock=="undefined")
//第一次的时候,Book.isLock是undefined,给原型绑定函数,以后就不需要了,他相比于构造函数原型模式的优点在于把所有的逻辑全部封装到构造函数里面!
  {
   alert("Enter!");
Book.prototype.what=function() 
     {
   alert(this.title+this.pages);
     }
   Book.isLock=true;
 }
}
//下面的两次调用alert("Enter!")只会调用因此i,因为第一次已经通过Book.isLock设置为true了!相当于静态方法!;
var b1=new Book("me",12);
b1.what();
var b2=new Book("he",13);
b2.what();

也可以在this中直接检测,而不用给函数对象一个属性

function Book(title,page)
{
 this.title=title;
 this.page=page;
  if(typeof this.sayName!='function')
  //第二次构造对象的时候会在原型中查找到sayName!
  {
   Book.prototype.sayName=function()
 {
  console.log(this.title);
 }
  }
}

5.寄生构造函数模式

除了使用new操作符以外,和工厂设计模式是一模一样的!可以在特殊的情况下为对象创建构造函数,例如想用构造函数方式创建一个具有额外方法的特殊数组,因为不能直接修改Array的构造函数,因此可以用这个模式!

function SpecialArray()
{
  var value=new Array();
  value.push.apply(value,arguments);
  value.toPipedString=function()
  {
    return this.join("|");
}
 return value;
}

总之,寄生构造函数的特点就是:有点像java中的装饰模式!把原来的对象进行装饰,同时返回装饰后的对象!这里就是把Array对象进行了装饰!添加了toPipe的String方法。缺点就是不能依赖instanceof操作符确定对象类型了,因为和不再包装类里面创建的对象是一模一样的!

6. 稳妥构造函数模式

特点:没有公共属性,而且其方法也不引用this的对象,instanceof失效。和寄生构造函数的不同在于不使用new来构造函数,同时实例方法不引用this。实际是闭包

function Person(name,age,job)
{
   var o=new Object();
    o.sayName=funciton(){alert(name)}//这里实例方法没有引用this,除了sayName不会有方法访问传入到构造函数中的原始数据!
   return o;
}
var friend=Person("xx",12,"teacher");
friend.name="female";//即使可以为这个对象修改了属性name
friend.sayName();//不会被修改,依然弹出xx。不是female。但是,如果把上面的修改成:o.sayName=function(){alert(this.name)}//那么就会弹出female,也就是friend.name被修改成功了,如果没有this,那么name的值一直引用的是原来的参数值!

感兴趣的朋友还可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试运行上述js代码。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
combox改进版 页面原型参考dojo的,比网上jQuery的那些combox功能强,代码更小
Apr 15 Javascript
jQuery创建插件的代码分析
Apr 14 Javascript
根据邮箱的域名跳转到相应的登录页面的代码
Feb 27 Javascript
随鼠标上下滚动的jquery代码
Dec 05 Javascript
浅谈js多维数组和hash数组定义和使用
Jul 27 Javascript
angular+ionic 的app上拉加载更新数据实现方法
Jan 16 Javascript
jQuery Masonry瀑布流插件使用方法详解
Jan 18 Javascript
实战node静态文件服务器的示例代码
Mar 08 Javascript
详解vue中axios的封装
Jul 18 Javascript
微信小程序 Animation实现图片旋转动画示例
Aug 22 Javascript
Koa日志中间件封装开发详解
Mar 09 Javascript
用Angular实现一个扫雷的游戏示例
May 15 Javascript
Vue.js图片预览插件使用详解
Aug 27 #Javascript
JavaScript中创建原子的方法总结
Aug 26 #Javascript
解决vue.js 数据渲染成功仍报错的问题
Aug 25 #Javascript
解决Vue.js由于延时显示了{{message}}引用界面的问题
Aug 25 #Javascript
vue中各选项及钩子函数执行顺序详解
Aug 25 #Javascript
vue实现在一个方法执行完后执行另一个方法的示例
Aug 25 #Javascript
JS Object.preventExtensions(),Object.seal()与Object.freeze()用法实例分析
Aug 25 #Javascript
You might like
php中cookie实现二级域名可访问操作的方法
2014/11/11 PHP
PHP统计目录大小的自定义函数分享
2014/11/18 PHP
php版微信公众平台接口参数调试实现判断用户行为的方法
2016/09/23 PHP
PHP实现多关键字加亮功能
2016/10/21 PHP
php版阿里大于(阿里大鱼)短信发送实例详解
2016/11/30 PHP
利用PHP获取网站访客的所在地位置
2017/01/18 PHP
ThinkPHP 3使用OSS的方法
2018/07/19 PHP
js arguments.callee的应用代码
2009/05/07 Javascript
js中top/parent/frame概述及案例应用
2013/02/06 Javascript
js清空表单数据的两种方式(遍历+reset)
2014/07/18 Javascript
JavaScript中定义函数的三种方法
2015/03/12 Javascript
第三篇Bootstrap网格基础
2016/06/21 Javascript
jQuery滚动新闻实现代码
2016/06/26 Javascript
AngularJs定制样式插入到ueditor中的问题小结
2016/08/01 Javascript
Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程
2017/05/07 Javascript
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
jQuery实现每隔一段时间自动更换样式的方法分析
2018/05/03 jQuery
React为 Vue 引入容器组件和展示组件的教程详解
2018/05/03 Javascript
nodejs提示:cross-device link not permitted, rename错误的解决方法
2019/06/10 NodeJs
ES6顶层对象、global对象实例分析
2019/06/14 Javascript
django中使用vue.js的要点总结
2019/07/07 Javascript
Node.js创建一个Express服务的方法详解
2020/01/06 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
js在HTML的三种引用方式详解
2020/08/29 Javascript
构建一个JavaScript插件系统
2020/10/20 Javascript
跟老齐学Python之使用Python查询更新数据库
2014/11/25 Python
设计模式中的原型模式在Python程序中的应用示例
2016/03/02 Python
深入浅析python 中的匿名函数
2018/05/21 Python
Python网络爬虫之爬取微博热搜
2019/04/18 Python
Django添加bootstrap框架时无法加载静态文件的解决方式
2020/03/27 Python
Python虚拟环境virtualenv创建及使用过程图解
2020/12/08 Python
Backcountry旗下的户外商品闪购网站:steep&cheap
2016/09/22 全球购物
习近平在党的群众路线教育实践活动总结大会上的讲话全文
2014/10/25 职场文书
社会实践单位意见
2015/06/05 职场文书
2016干部作风整顿心得体会
2016/01/22 职场文书
python超详细实现完整学生成绩管理系统
2022/03/17 Python