JavaScript实现创建自定义对象的常用方式总结


Posted in Javascript onJuly 09, 2018

本文实例讲述了JavaScript实现创建自定义对象的常用方式。分享给大家供大家参考,具体如下:

1. 对象字面量方式

对象字面量方式是创建自定义对象的首选模式,简单方便。

var per = {
 name:'zhangsan',
 age:25,
 job:'html',
 sayName:function(){
  alert(this.name);
 }
}

缺点:使用同一个接口创建很多对象,会产生大量的重复代码。比如我想再创建一个per1对象,我就得把上面的代码再重新写一遍,改变不同的属性值。

2、工厂模式

工厂模式抽象了创建具体对象的过程。由于在ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下面的例子:

function createPerson(name,age,job){
 var o = new Object();
 o.name = name;
 o.age = age;
 o.job = job;
 o.sayName = function(){
  alert(this.name);
 }
 return o;
}
var person1 = createPerson('zhang',30,'java');
var person2 = createPerson('zhao',25,'php');

函数createPerson()能够根据接受到的参数来构建一个包含所有必要信息的Person对象。可以无数次的调用这个函数,而每次它都会返回一个包含三个属性和一个方法的对象。

缺点:工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。

3、构造函数模式

可以使用构造函数模式将前面的例子重写如下:

function Person(name,age,job){
 this.name= name;
 this.age = age;
 this.job = job;
 this.sayName = function(){
  alert(this.name);
 }
}
var person1 = new Person('zhang',30,'java');
var person2 = new Person('zhao',25,'php');

创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型。而这正是构造函数模式胜过工厂模式的地方。

然而,使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。在上面的例子中,person1和person2都有一个名为sayName()的方法,但那两个方法不是同一个Function的实例,创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此可以像下面这样,通过把函数定义转移到构造函数外部来解决这个问题。

function Person(name,age,job){
 this.name= name;
 this.age = age;
 this.job = job;
 this.sayName = sayName();
}
function sayName(){
  alert(this.name);
}
var person1 = createPerson('zhang',30,'java');
var person2 = createPerson('zhao',25,'php');

在这个例子中,我们把sayName()函数的定义转移到构造函数外部。而在构造函数内部,我们将sayName属性设置成等于全局的sayName函数,这样person1和person2对象就共享了在全局作用域中定义的同一个sayName()函数。这样确实解决了两个函数在做同一件事的问题,可是新问题又来了:在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多全局函数。好在,这些问题可以通过使用原型模式来解决。

4、原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的好处是可以让所有的对象实例共享他所包含的属性和方法。

function Person(){}
Person.prototype.name = 'zhang';
Person.prototype.age = '22';
Person.prototype.job = 'html5';
Person.prototype.sayName = function(){
 alert(this.name);
};
var person1 = new Person();
var person2 = new Person();

原型模式也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值。虽然这会在某种程度上带来一些不方便,但还不是原型的最大问题。原型模式的最大问题是由共享的本性所导致的。

原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒也说的过去,通过在实例上添加一个同名属性,可以隐藏原型中的对应属性。然后,对于包含引用类型的属性来说,问题就比较突出了。

function Person(){}
Person.prototype = {
 constructor:Person,
 name:'zhang',
 age :'22',
 job :'html5',
 friends:['wang','li'],
 sayName : function(){
  alert(this.name);
 }
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push('zhao');
alert(person1.friends); //'wang,li,zhao'
alert(person2.friends); //'wang,li,zhao'
alert(person1.friends === person2.friends); //true

从上面的打印的结果我们就可以知道为什么很少人单独使用原型模式了,实例一般都是要有属于自己的全部属性的。

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

组合使用构造函数模式和原型模式,是创建自定义类型的最常见方式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度的节省了内存。

function Person(name,age,job){
 this.name= name;
 this.age = age;
 this.job = job;
 this.friends = ['wang','li'];
}
Person.prototype = {
 constructor:Person,
 sayName : function(){
  alert(this.name);
 }
}
var person1 = new Person('zhang',26,'java',);
var person2 = new Person('sun',25,'php');
person1.friends.push('zhao');
alert(person1.friends); //'wang,li,zhao'
alert(person2.friends); //'wang,li'
alert(person1.friends === person2.friends); //false

在上面的例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性constructor和方法satName()则是在原型中定义的。而修改了person1.friends(向其中添加一个新字符串),并不会影响到person2.friends,因为他们分别引用了不同的数组。

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

Javascript 相关文章推荐
根据IP的地址,区分不同的地区,查看不同的网站页面的js代码
Feb 26 Javascript
将HTML的左右尖括号等转义成实体形式的两种实现方式
May 04 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
Oct 17 Javascript
javascript将url中的参数加密解密代码
Nov 17 Javascript
jQuery预加载图片常用方法
Jun 15 Javascript
js基本算法:冒泡排序,二分查找的简单实例
Oct 08 Javascript
JS简单获取当前年月日星期的方法示例
Feb 07 Javascript
windows下vue.js开发环境搭建教程
Mar 20 Javascript
vue 实现类似淘宝星级评分的示例
Mar 01 Javascript
详解基于Vue cli生成的Vue项目的webpack4升级
Jun 19 Javascript
4个顶级JavaScript高级文本编辑器
Oct 10 Javascript
js实现坦克大战游戏
Feb 24 Javascript
vue-cli配置环境变量的方法
Jul 09 #Javascript
JS逻辑运算符短路操作实例分析
Jul 09 #Javascript
微信小程序中时间戳和日期的相互转换问题
Jul 09 #Javascript
使用async await 封装 axios的方法
Jul 09 #Javascript
bootstrap 弹出框modal添加垂直方向滚轴效果
Jul 09 #Javascript
jQuery实现简单复制json对象和json对象集合操作示例
Jul 09 #jQuery
JS实现图片旋转动画效果封装与使用示例
Jul 09 #Javascript
You might like
php图片上传存储源码并且可以预览
2011/08/26 PHP
php定时计划任务的实现方法详解
2013/06/06 PHP
php7安装yar扩展的方法详解
2017/08/03 PHP
IE 上下滚动展示模仿Marquee机制
2009/12/20 Javascript
JavaScript基础篇之变量作用域、传值、传址的简单介绍与实例
2013/06/29 Javascript
Javascript和HTML5利用canvas构建Web五子棋游戏实现算法
2013/07/17 Javascript
javascript文本框内输入文字倒计数的方法
2015/02/24 Javascript
jQuery flip插件实现的翻牌效果示例【附demo源码下载】
2016/09/20 Javascript
JS实现双击内容变为可编辑状态
2017/03/03 Javascript
jQuery动态添加.active 实现导航效果代码思路详解
2017/08/29 jQuery
(模仿京东用户注册)用JQuery实现简单表单验证,初学者必看
2018/01/08 jQuery
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
详解开发react应用最好用的脚手架 create-react-app
2018/04/24 Javascript
vue中设置、获取、删除cookie的方法
2018/09/21 Javascript
Node.js从字符串生成文件流的实现方法
2019/08/18 Javascript
超详细小程序定位地图模块全系列开发教学
2020/11/24 Javascript
[03:17]2014DOTA2 国际邀请赛中国区预选赛 四强专访
2014/05/23 DOTA
[20:57]Ti4主赛事第三天开幕式
2014/07/21 DOTA
[54:28]EG vs OG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
在Django中管理Users和Permissions以及Groups的方法
2015/07/23 Python
pyqt5 实现多窗口跳转的方法
2019/06/19 Python
python 实现交换两个列表元素的位置示例
2019/06/26 Python
Python实现AI自动抠图实例解析
2020/03/05 Python
python爬虫利器之requests库的用法(超全面的爬取网页案例)
2020/12/17 Python
python 制作网站小说下载器
2021/02/20 Python
H&M美国官网:欧洲最大的服饰零售商
2016/09/07 全球购物
Herve Leger官网:标志性绷带连衣裙等
2018/12/26 全球购物
学生实习推荐信范文
2013/11/26 职场文书
入党思想汇报怎么写
2014/04/03 职场文书
金融与证券专业求职信
2014/06/22 职场文书
2014年党支部书记工作总结
2014/12/04 职场文书
高中升旗仪式主持词
2015/07/03 职场文书
致运动员的广播稿
2015/08/19 职场文书
教师教育心得体会
2016/01/19 职场文书
《花钟》教学反思
2016/02/17 职场文书
PostgreSQL出现死锁该如何解决
2022/05/30 PostgreSQL