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 相关文章推荐
asp.net网站开发中用jquery实现滚动浏览器滚动条加载数据(类似于腾讯微博)
Mar 14 Javascript
jquery 卷帘效果实现代码(不同方向)
Feb 05 Javascript
javascript实现的一个随机点名功能
Aug 26 Javascript
Vue.js系列之vue-router(上)(3)
Jan 03 Javascript
使用Angular缓存父页面数据的方法
Jan 03 Javascript
js实现文字列表无缝滚动效果
Jun 23 Javascript
JavaScript中重名的函数与对象示例详析
Sep 28 Javascript
JavaScript模拟实现封装的三种方式及写法区别
Oct 27 Javascript
详解Vue CLI3 多页应用实践和源码设计
Aug 30 Javascript
使用Vue中 v-for循环列表控制按钮隐藏显示功能
Apr 23 Javascript
js核心基础之构造函数constructor用法实例分析
May 11 Javascript
Vue的transition-group与Virtual Dom Diff算法的使用
Dec 09 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查找数值数组中不重复最大和最小的10个数的方法
2015/04/20 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
js null,undefined,字符串小结
2010/08/21 Javascript
鼠标右击事件代码(asp.net后台)
2011/01/27 Javascript
最短的javascript:地址栏载入脚本代码
2011/10/13 Javascript
Tab切换组件(选项卡功能)实例代码
2013/11/21 Javascript
jQuery.event兼容各浏览器的event详细解析
2013/12/18 Javascript
简介JavaScript中valueOf()方法的使用
2015/06/05 Javascript
jQuery支持添加事件的日历特效代码分享(3种样式)
2015/08/24 Javascript
vue将对象新增的属性添加到检测序列的方法
2018/02/24 Javascript
jQuery中实现text()的方法
2019/04/04 jQuery
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
react中hook介绍以及使用教程
2020/12/11 Javascript
Python 正则表达式的高级用法
2016/12/04 Python
python2与python3共存问题的解决方法
2018/09/18 Python
Pycharm代码无法复制,无法选中删除,无法编辑的解决方法
2018/10/22 Python
对Python+opencv将图片生成视频的实例详解
2019/01/08 Python
python解析含有重复key的json方法
2019/01/22 Python
python 实现绘制整齐的表格
2019/11/18 Python
python接口自动化如何封装获取常量的类
2019/12/24 Python
flask框架蓝图和子域名配置详解
2020/01/25 Python
python 链接sqlserver 写接口实例
2020/03/11 Python
TensorFlow的reshape操作 tf.reshape的实现
2020/04/19 Python
用Python 爬取猫眼电影数据分析《无名之辈》
2020/07/24 Python
python判断一个变量是否已经设置的方法
2020/08/13 Python
如何快速一次性卸载所有python包(第三方库)呢
2020/10/20 Python
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
台湾时尚彩瞳专门店:imeime
2019/08/16 全球购物
Otiumberg官网:英国半精致珠宝品牌
2021/01/16 全球购物
物流业务员岗位职责
2014/02/08 职场文书
《李时珍夜宿古寺》教学反思
2014/04/09 职场文书
学校关爱留守儿童活动方案
2014/08/27 职场文书
劳动仲裁调解书
2015/05/20 职场文书
防卫过当辩护词
2015/05/21 职场文书
Python基础之变量的相关知识总结
2021/06/23 Python