• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > JavaScript中创建对象的7种模式详解

JavaScript中创建对象的7种模式详解

作者:nick906 字体:[增加 减小] 来源:互联网 时间:2017-05-11

nick906通过本文主要向大家介绍了javascript面向对象,javascript event对象,javascript对象,javascript内置对象,javascript date对象等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

ECMA-262把对象定义为:”无需属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲,这就相当于说明对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正因为这样,我们可以把ECMAScript的对象想象成散列表:无非就是一组名对值,其中值可以是数据或函数。

创建自定义对象最简单的方式就是创建一个Object的实例,然后再为他添加属性和方法,如下所示:

var person = new Object();、person.name = "liubei";person.age = 29;
person.job = "shayemuyou";
person.sayName = function(){ 
 alert(this.name);
}
</div>

上面的例子创建了一个名为person的对象,并为他添加了三个属性和一个方法。其中sayName()方法用于显示name属性,this.name将被解析为person.name,早期的开发人员经常使用这个模式来创建对象,后来对象字面量的方法成了创建对象的首选模式,上面的例子用对象字面量的语法可以写成如下这样:

var person = { 
 name:"liubei", 
 age:29, 
 job:"shayemuyou", 
 sayName:function(){  
 alert(this.name); 
 }
}
</div>

这个例子中的person对象和前面的对象是一样的,都有相同的属性和方法。

虽然Object构造函数或者对象字面量的方法都可以用来创建单个对象,但是这些方法有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为了解决这个方法,人们开始使用工厂模式的一种变体。

一、工厂模式

工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程。考虑到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("wei",25,"software");
var person2 = createPerson("bu",25,"software");
</div>

函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。可以多次调用这个函数,每次都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题,即怎么样知道这是哪个对象类型。

二、构造函数模式

像Array、Object这样的原生构造函数,在运行时会自动出现在执行环境中。此外,我们可以创建自定义个构造函数,从而定义自定义类型的属性和方法。例如,我们可以使用构造函数重写上个例子:

function Person(name, age, job){ 
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = function(){  
   alert(this.name); 
  }
}
var person1 = new Person("wei",25,"software");
var person2 = new Person("bu",25,"software");
</div>

在这个例子中,Person()函数取代了createPerson()函数,我们注意到Person()与createPerson()的不同之处在于:

没有显式的创建对象

直接将属性和方法赋值给this对象

没有return语句

此外,还应该注意到函数名Person使用的是大写字母P。按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头。这个做法借鉴了其他OO语言,主要是为了区别于ECMAScript中的其他函数。因为构造函数本身也是函数,只不过可以创建对象而已。

要创建一个Person实例,必须使用new操作符。以上这种方式会经过以下四个步骤:

1、创建一个新对象

2、将构造函数的作用域赋给新对象(因此this指向这个新对象)

3、执行构造函数中的代码

4、返回新对象

在前面例子的最后,person1和person2分别保存着Person的一个不同的实例。这两个对象都有一个constructor(构造函数)属性,该属性指向Person。如下:

console.log(person1.constructor == Person); //true
console.log(person2.constructor == Person); //true
</div>

对象的constructor属性最初是用来标识对象类型的。但是,提到检测对象类型,还是instanceof操作符比较可靠一些。我们在这个例子中创建的对象都是Object对象的实例,也是Person对象的实例,这一点通过instanceof操作符可以验证。

console.log(person1 instanceof Object);
//trueconsole.log(person1 instanceof Person);
//trueconsole.log(person2 instanceof Object);
//trueconsole.log(person2 instanceof Person);
//true
</div>

创建自定义的构造函数意味着将来可以将他的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。在这个例子中,person1和person2之所以同是Object的实例,是因为所有的对象都继承自Object。

构造函数的主要问题,就是每个方法都要在实例上重新创建一遍,造成内存浪费。在前面的例子中,person1和person2都有一个名为sayName()的方法,但是两个方法不是同一Function的实例。不要忘了ECMAScript中的函数也是对象,因此每定义一个函数,也就是实例化了一个对象,从逻辑角度讲,此时的构造函数可以这样定义:

function Person(name, age, job){ this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = new Function("alert(this.name);")
 //与声明函数在逻辑上是等价的
 }
</div>

从这个角度来看构造函数,更容易看明白每个Person实例都会包含一个不同的Function实例的本质。说明白些,会导致不同的作用域链和标识符解析,但是创建Function新实例的机制仍然是相同的。因此,不同实例上的同名函数是不相等的,以下代码可以证实这一点。

alert(person1.sayName == person2.sayName);  //false

然而,创建两个完成同样任务的Function实例的确没有必要;况且有this对象在,根本不用在执行代码前就把函数绑定到特定的对象上。因此,可以像下面这样,通过把函数定义转移到构造函数外部来解决这个问题。

function Person(name, age, job){
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = sayName;
}
function sayName(){
 alert(this.name);
}
</div>

这样做解决了多个函数解决相同问题的问题,但是有产生了新的问题,在全局作用域中实际上只被某个对象调用,这让全局对象有点名不副实。更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。好在这些问题可以使用原型模式来解决。

三、原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。使用原型对象的实例就是让所有实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象的实例信息,而是可以将这些信息直接添加到原型对象中,如下所示:

function Person(){
}
Person.prototype.name = "wei";
Person.prototype.age = 27;
Person.prototype.job = "Software";
Person.prototype.sayName = function(){
 alert(this.name);
}
var person1 = new Person();
person1.sayName();  //"wei"
var person2 = new Person();
person2.sayName();  //"wei"
alert(person1.sayName == person2.sayName);
</div>

在此,我们将sayName()方法和所有的属性直接添加在了Person的prototype属性中,构造函数变成了空函数。即便如此,我们仍然可以通过构造函数来创建新对象,而且新对象还会具有相同的属性和方法。但是与构造函数不同的是,新对象的这些属性和方法是由所有实例共享的。换句话说,person1和person2访问的都是同一组属性和同一个sayName()函数。要理解原型模式的工作原理,就必须先理解ECMAScript中原型对象的性质。

原型对象的本性由于篇幅太长将会在下一章节详细分析。上面我们说了原型模式的好处,接下来我们来看一下原型模式的缺点。原型模式省略了为构造函数传递参数的这一环节,结果所有实例在默认情况下都具有相同的属性值。这会在某些程度上带来一种不便,这并不是原型模式最大的问题,因为如果我们想为一个通过原型模式创建的对象添加属性时,添加的这个属性就会屏蔽原型对象的保存的同名属性。换句话说,就是添加的这个属性会阻止我们去访问原型中的属性,但并不会改变原型中的属性。

原型模式最大的问题是由其共享的本质所导致的。原型中所有的属性被很多实例共享,这种共

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • javascript 判断一个对象为数组的方法
  • javascript 面向对象function详解及实例代码
  • JavaScript中创建对象的7种模式详解
  • Javascript基础回顾之(三) js面向对象
  • JavaScript中String对象的方法介绍

相关文章

  • 2017-05-11Javascript 链式作用域详细介绍
  • 2017-05-11基于JS实现仿百度百家主页的轮播图效果
  • 2017-05-11AngularJS表单基本操作
  • 2017-05-11vue组件中点击按钮后修改输入框的状态实例代码
  • 2017-05-11vue.js利用Object.defineProperty实现双向绑定
  • 2017-05-11JavaScript常用正则函数用法示例
  • 2017-05-11easyui关于validatebox实现多重规则验证的方法(必看)
  • 2017-05-11jQuery插件echarts实现的单折线图效果示例【附demo源码下载】
  • 2017-05-11Vue.js实现模拟微信朋友圈开发demo
  • 2017-05-11vuejs响应用户事件(如点击事件)

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 微信小程序 弹窗自定义实例代码
    • vue.js父组件使用外部对象的方法示例
    • Javascript实现页面滚动时导航智能定位
    • js自制图片放大镜功能
    • VUE开发一个图片轮播的组件示例代码
    • 基于javascript实现数字英文验证码
    • 详解angularjs结合pagination插件实现分页功能
    • Jquery鼠标放上去显示全名的实现方法
    • 复制网页内容后自动添加版权文字的方法(兼容IE、Firefox和Chrome)
    • 详解Javascript几种跨域方式总结

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有