随着AJAX的大行其道,对于JavaScript的面向对象编程的需求就显得极为迫切,因为大量的客户应用代码需要在客户端处理,为了增加客户端代码的开发效率,我们不得不使用面向对象的编程方式来封装我们的代码,用来构建我们自己的开发框架。
虽然JavaScript本身就是构建在对象的基础上的一个语言。我们在使用它的时候,你会发觉对象无处不在,其中包含其自身的内部对象原形Array,Boolean,Date,Math,Nummber,Object,String,Function,RegExp,Global,Enumerator,Error,以及浏览器中的DOM对象等等……。但是Javascript本身并不提供class声明语法来创建对象。虽然JScript.NET版本已经提供了class语句来声明对象,和private,public等常见的封装对象的语句,但是要求是客户端必须拥有.NET Framework的支持,总所周知.NET平台现在只局限于企业级应用,以及服务器端的应用。还并没有普及到普通PC上来,所以我们使用JScript.NET版本开发客户端应用就有点的得不偿失了。况且我们为了满足客户的需求还需要兼容其它的浏览器,所以JScript.NET在这里我们暂且不提。
那我们怎么创建自己的对象呢?
网上流传了很多创建对象的方法,我在这里举例说明,并且分析一下为什么可以这么写。
首先是基于Object原形实例的对象:
//示例
var MyObj = new Object();
MyObj.Msg = "My Message"
MyObj.ShowMsg = function()//创建一个Msg的方法用以在屏幕上显示一个对话框的内容
{
window.alert(this.Msg)
}
MyObj.Msg()//调用该方法
这时我们发现基于原形实例的对象,我们虽然可以创建出一个对象并且可以直接用.的方法添加新的属性,但是我们发现我们不能创建私有成员,并且不能拥有继承,所以这种方法创建对象并不是我们所需要的,我们pass他
基于Array原形实例的对象:
//示例
var MyObj = new Array();
MyObj.Msg = "My Message"
MyObj.ShowMsg = function()
{
window.alert(this.Msg)
}
MyObj.Msg()//调用该方法
我们发现它和基于Object原形实例的对象是一样的,所以也不用考虑。
但他的另一种写法,我们可以在这里提一下
var MyObj = {
Msg:"My Message",//注意这后面的","号,因为我们使用数组直接创建的对象所以他遵循数组的书写规范
ShowMsg:function()
{
window.alert(this.Msg)
}
}
其实说到这里,我们不难看出,其实在JavaScript里对象就是用关联数组来实现的,又因为它是一个弱类型的语言,它的值可以是任何类型,当然也包含函数类型。所以我们可以用这种方式来实现一个对象实例。
基于function的封装类:
现在我们谈到的类的封装,因为使用function创建的类(我们暂且叫它类,其实它并不是一个类,只是一个Function原形的一个实例,仅此而已),我们可以在创建新的实例的时候自动的添加其成员。至于他在解释器内部是如何创建的,我们稍候再谈。先来看一个例子。
function MyObj()
{
this.Msg = "My Message"
this.ShowMsg = function()
{
window.alert(this.Msg)
}
}
当然我们也可以把它的成员写在外面,如下:
function MyObj()
{
this.Msg = "My Message"
}
MyObj.prototype.ShowMsg = function()
{
window.alert(this.Msg)
}
在这里我们需要理解一个概念,这两个例子只是创建了一个Function类型的一个实例MyObj,第二种方法是在外部给这个实例添加一个功能属性,这个功能属性是一个函数。
之后我们就可以用这个函数创建我们自己的对象了,
例如:
var Obj = new MyObj()
Obj.ShowMsg()
为什么这样写?在回答这个问题之前,我们需要掌握两个概念:
一:this是什么?
this在官方的文档里描述为当前对象,何谓当前对象?就是当前这个函数或变量是属于那个对象的。一般在我们的所有函数以及变量都是定义在window对象里的,所以如果你直接在<script>标签里调用this是恒等于window对象的。但我们不能用this调用我们在<script>标签内定义的函数和变量,这个我们稍候再谈。
二:new到底干了些什么?
new在官方的文档里描述为使用构造函数来创建对象,并返回其对象。在这里,我们的构造函数是MyObj(),new方法在使用的时候创建一个空的对象,并执行我们后面所跟的函数,在这里我们的MyObj()函数在运行的时候分别给this添加了两个属性Msg,ShowMsg并且将MyObj的prototype方法复制给this,这里的this引用的就是我们new语句创建的对象。其本质和给Object原形创建的实例添加属性的方法是一样的。
我们来稍微改写一下,也许您就更容易理解上面这种写法都作了些什么。
示例:
var Obj = new Object()
function MyObj()
{
Obj.Msg = "My Message"
Obj.ShowMsg = function()
{
window.alert(this.Msg)
}
}
MyObj()
Obj.ShowMsg()
也许这样更容易理解一些
好!到现在我们已经用Javascript所拥有的语言特性模拟出来了一个简单的类,但还是没有满足一个类私有属性封装的需求,现在我们再来看一个例子
function MyObj()
{
var MsgContent = "Apple"
this.Msg = "LeoWoo"
this.ShowMsg = function()
{
window.alert(this.Msg+"'s "+MsgContent)
}
}
var Obj = new MyObj()
Obj.ShowMsg()
我们惊奇的发现MyObj函数里定义的MsgContent竟然可以访问!!这在我们以前在其他语言里的函数是不可能的,因为在我们前面所分析过的,MyObj函数只在创建实例的时候运行过一次,MsgContent因该在MyObj函数运行过后就自动销毁了啊?难道他类似于其他语言的局部静态变量?答案是肯定的,这个变量在MyObj函数运行过后还继续存在,那么它确实是一个静态变量。但是现在问题又来了,我们前面分析过,用MyObj函数在创建Obj时ShowMsg属性被添加到了Obj里,他何来的权限访问一个函数里定义的变量呢?这里我们需要注意到几点。试想一下,如果这个MsgContent变量和ShowMsg函数没有定义到函数体里,那ShowMsg可以访问MsgContent那就理所应当了。
例如这样:
var MsgContent = "Apple"
ShowMsg = function()
{
window.alert(MsgContent)
}
顺便说一下,在Javascript里函数定义有多种写法
如:函数名 = function(){}或者function 函数名(){}这两者是一样的
好了,现在我们明白为什么Obj.ShowMsg可以有权限调用MyObj函数里定义的局部变量MsgContent了吧,因为ShowMsg所引用的函数定义是在MyObj函数里,并且和MsgContent是平级的,只不过在MyObj函数运行的时候把这个函数引用添加到了new语句创建的新对象里,并且引用赋值给了Obj变量。
当然,如果你用MyObj.prototype.ShowMsg方法在外部添加的话,你就没有权限访问MyObj函数里定义的局部变量MsgContent的。
现在我们解决了怎样用一个函数创建一个对象,并且可以设置私有属性和公有属性,那我们是不是还缺个继承?
我们来看这个例子:
function NewObj()
{
this.Base = MyObj
this.Base()
this.SetMsg = function(PMsg)
{
this.Msg = PMsg
}
}
var Obj = new NewObj()
Obj.SetMsg("六月初六")
Obj.ShowMsg()
这个例子我们结合刚才的那个function MyObj()例子,我们发现NewObj()创建的对象包含MyObj()里需要创建的属性,这是为什么呢?从刚才我们分析的以前的那几个例子当中我们就不难理解为什么这样写就可以轻松实现继承了。因为在NewObj函数运行时,调用了MyObj函数,所以两个函数同时将新对象的属性赋值,这样就模拟了类的继承。
明眼人一定发现,同样是运行,我为什么不直接写MyObj()来运行,而要写成this.Base = MyObj;this.Base()的方式来运行呢?细想一下,MyObj函数可是定义在<script>标签里的,NewObj函数调用它的时候,MyObj函数里的this可不是新建的对象,而是window对象,如果你这样写,就等于是在window对象里添加属性了,而我们先在NewObj函数运行时给新对象this添加一个属性,并且将MyObj函数引用赋值给他,那这时MyObj是否就成了新对象里的一个方法了?我们运行新对象里的方法,那其this就等于当前对象,这样我们的继承也就模拟出来了。
当然我们也可以模拟继承多个类,在这我就不多说了。
至于重载,也就是给对象属性从新赋一个值,我在这就不在做讨论分析了。
在我们给对象属性赋值的时候需要运行一些代码怎么办?
在其他语言里如VB我们可以用如下代码:
Class MyObj
Public cMsg
Public Property Get Msg
Msg = cMsg
End Property
Public Property Let Msg(PMsg)
vMsg = PMsg
End Property
End Class
C++可以用运算符重载
C#可以用get,set关键词等等……
那我们JavaScript怎么做到呢?我们可以用类似Java分别做set_Msg和get_Msg两个函数来做,当然也我们也可以模拟。
在我们的Function里有一个属性argument可以帮助我们实现这一梦想,argument这个属性是一个数组,他的值就是我们的函数传进来的参数数组,我们可以用它来模拟实现函数重载。我们可以这样写
function MyObj()
{
this.cMsg = ""
this.Msg=function()
{
if(argument.length==1)
{
this.cMsg = argument[0]
}
return this.cMsg
}
}
var Obj = new MyObj()
Obj.Msg("leowoo")
window.alert(Obj.Msg())
看到这里我们也许需要在给属性赋值的时候触发一个事件来运行一个外部函数怎么办?
我们前面讨论到,JavaScript的变量可以是任意类型的对象,他当然也可以是一个函数引用,所以我们只需要在对象里给出一个空属性让其他程序来给他赋值一个方法就可以了,然后我们再需要运行的地方调用它,虽然他可能不存在。
代码如下:
function MyObj()
{
this.cMsg = ""
this.onMsg = null
this.Msg=function()
{
if(argument.length==1)
{
if(typeof this.onMsg == "function")
{
this.onMsg()
}
this.cMsg = argument[0]
}
return this.cMsg
}
}
var Obj = new MyObj()
Obj.onMsg = function()
{
window.alert("onMsg")
}
Obj.Msg("leowoo")
window.alert(Obj.Msg())
当然我们也可以传值给这个事件
部分代码如下:
if(typeof this.onMsg == "function")
{
this.onMsg(this.Msg)
}
…………
Obj.onMsg = function(PMsg)
{
window.alert("onMsg "+PMsg)
}
好了,现在我们用JavaScript模拟类的实现基本就算结束了,如果还有什么需要补充的或疑问,请联系我QQ:27860381
有时间我在整理一下JavaScript模拟模板技术是怎样实现的。
LeoWoo(六月初六)
写于2006年8月3号 下午4点
修改于2006年8月9号 下午6点
分享到:
相关推荐
DeePool通过实现JavaScript对象池,为开发者提供了一种优化内存使用、提高程序运行效率的有效手段。尤其在需要大量创建和销毁对象的场景下,使用DeePool可以显著提升性能,减少内存压力。掌握并合理运用DeePool,...
每个JavaScript对象都有一个`__proto__`属性,指向创建该对象的构造函数的原型。原型对象也是一个对象,可以通过`prototype`属性来访问。我们可以在原型上定义方法,这样所有实例都可以访问这些方法: ```...
在JavaScript(JS)中,对象是一种复杂的数据结构,...总的来说,JavaScript对象属性排序是一个需要谨慎处理的问题,因为它们的天然无序性。理解这些方法和原理,可以帮助我们在开发中更好地控制和处理对象的属性顺序。
JavaScript内置对象相关介绍及用法ppt JavaScript内置对象相关介绍及用法
JS 面向对象经典案例 在JavaScript中,面向对象编程是非常重要的一部分。它提供了一种创建和组织代码的方式,能够让开发者更好地组织和维护代码。在本文中,我们将介绍JavaScript面向对象编程中的经典案例,包括...
有关js对象的操作和遍历对象小练习带注释.html
// 将JavaScript对象转换为JSON字符串 var jsonString = JSON.stringify(person); console.log(jsonString); // 将JSON字符串转换回JavaScript对象 var parsedPerson = JSON.parse(jsonString); console.log...
JavaScript(简称JS)是Web开发中的重要脚本语言,尤其在客户端编程中不可或缺。本文将深入探讨JS对象的实例创建、属性与...通过不断的实践和学习,开发者可以运用JS对象解决各种实际问题,提升开发效率和代码质量。
JavaScript之Date对象(源代码)JavaScript之Date对象(源代码)JavaScript之Date对象(源代码)JavaScript之Date对象(源代码)JavaScript之Date对象(源代码)JavaScript之Date对象(源代码)JavaScript之Date对象...
在JavaScript编程中,获取对象和数组的属性键值(key)和对应值(value)是一项基本操作。本文将详细介绍如何实现这一功能,并提供相应的代码示例。 首先,我们需要理解JavaScript中的对象和数组。对象是一种键值对...
JavaScript之Math对象(源代码)JavaScript之Math对象(源代码)JavaScript之Math对象(源代码)JavaScript之Math对象(源代码)JavaScript之Math对象(源代码)JavaScript之Math对象(源代码)JavaScript之Math对象...
每个JavaScript对象都有一个`__proto__`属性,指向它的构造函数的原型。当试图访问对象的一个属性时,如果该对象上没有这个属性,JavaScript会查找其`__proto__`,再找不到就继续查找`__proto__`的`__proto__`,直到...
### JavaScript对象模型-执行模型详解 #### 一、基本数据类型 JavaScript作为一种广泛使用的脚本语言,在其设计之初便提供了一系列的基本数据类型,这些类型构成了JS语言的基础,并且是理解和运用JS的重要基石。 ...
### 现代JavaScript编程与面向对象特性 #### 引言 随着JavaScript的不断发展与成熟,这门语言已经成为全球范围内企业与开发者构建多样化应用的首选工具。从最初的简单脚本语言,JavaScript已演变成为功能全面、...
javaScript对象大全-javaScript必备手册-JS资料-JS教程.doc
document 对象.html-javascript中DOM对象内容
同时,他们也将学习如何扩展JavaScript内置对象,以及原型链在实际问题中的应用,例如在不使用额外库的情况下,实现字符串反转等实用功能。 总的来说,这个练习旨在让学习者掌握JavaScript中原型对象和原型链的核心...
JavaScript作为一门浏览器语言的核心思想;面向对象编程的基础知识及其在... 《JavaScript面向对象编程指南》着重介绍JavaScript在面向对象方面的特性,展示如何构建强健的、可维护的、功能强大的应用程序及程序库
与Java不同,JavaScript的标准类较少,如Date、Array、RegExp等,因此自定义对象成为解决这类问题的关键。 1.2 基本概念 1.2.1 自定义对象 在JavaScript中,自定义对象可以通过对象字面量或构造函数来创建,以扩展...
目标掌握: javascript内置对象 String 对象 Math 对象 Date 对象 浏览器对象 浏览器对象简介 Window Document History Location Screen event