轻松拿上JavaScript(三)——创建对象,构造方法,成员
我们这节讲到:如何创建自己的对象,如何创建构造方法,如何创建公有、私有、特权、静态成员。
如何创建自己的对象:我们从以下三点来讲:
1、我们从最简单的例子开始:var myObject=new Object();还有一种等价的方式:var myObject={};无论从哪种方式最终的myObject变量都是Object对象的实例,他作为一个对象的存在外没有任何其他作用。
2、实例化的过程,首先通过new关键字告知JS创建一个全新对象。然后新建的实例被赋值给一个变量,以便你可以通过引用那个变量来访问对象的新实例。不过为了做到这一点所实例化的对象必须是一个构造函数。
3、每个核心对象,例如:Object、Function、Array和String都含有构造函数。
当完成对象实例化之后就不能再基于新实例使用new关键字创建例外的实例了。
var anotherObj=new myObject();
就会报错,说myObject不是构造函数:我们看一下:
<title>创建自己的对象</title> </head> <body> <script type="text/javascript"> var myObject={};//new Object(); alert(""); </script> </body>
我们现在创建了一个myObject对象,那么我们继而创建的话:
<title>创建自己的对象</title> </head> <body> <script type="text/javascript"> var myObject={};//new Object(); var obj=new myObect(); alert(""); </script> </body>
就会报错。
如何来创建构造函数:
1、Function是创建构造函数的起点。
<script type="text/javascript"> function myConstructor(a){ /*某些代码*/ } </script>
2、上面的代码等价于下面的代码:
<script type="text/javascript"> var myConstructor=new Function('a','/*某些代码*/'); </script>
3、下面使用new的方式有性能问题所以不推荐使用。
4、Function对象的特别之处在于,它的实例也能作为构造方法,因此可以用来创建函数的新实例。所以可以编写下面的代码:
<script type="text/javascript"> function myConstructor(a){ /*某些代码*/ } var myObject=new myConstructor(); </script>
此时,myConstructor函数可以作为构造函数。当对象被实例之后,构造函数会执行包含的代码。
<script type="text/javascript"> var myObject={};//new Object(); function myConstructor(message){ /*某些代码*/ alert(message); this.myMessage=message; } var myObj=new myConstructor('helo world'); alert(""); </script>
显示的结果为:
在这个例子里边:我们要记住一下2点:
1、this引用的是myObj实例,通过将message参数赋值给this.myMessage使myObj拥有一个可以随时访问的名为myMessage的属性。var message=myObj.myMessage;
2、myMessage属性只在被实例化的myConstructor的实例中可用,而再myConstructor函数自身中是无效的:
function myConstructor(message){ this.myMessage="abc"; } alert(myConstructor.myMessage);
若是能运行成功,应该显示的是:abc。对吧。但是结果是:
这就说明了咱们的那个结论。
添加静态方法:
<script type="text/javascript"> var myObject=new Object(); //添加一个属性 myObject.name='jh'; //添加一个方法 myObject.alertName=function(){ alert(this.name); } //执行添加的办法 myObject.alertName(); </script>
打印出了jh。
在上面的代码中我们通过点运算符直接在myObject对象上将name属性和alertName()方法作为静态成员添加到了对象实例中。而此处恰恰是最容易导致误解的地方。因为这里的静态成员只存在于对象的一个个具体实例而不存在于构造函数中。
如果以Function对象为起点,也存在同样的问题,只不过这次的对象实例同时也是一个构造函数。
var myConstructor=function(){ } myConstructor.name='jh'; myConstructor.alertName=function(){ alert(this.name); } myConstructor.alertName();
这里的代码也能正常运行,因为myConstructor既是一个实例也是一个构造函数,但是name和alertName成员不能应用到任何新的实例中。如果创建myConstructor的实例,会报错如下面的代码:
<script type="text/javascript"> var myConstructor=function(){ } myConstructor.name='jh'; myConstructor.alertName=function(){ alert(this.name); } //myConstructor.alertName(); var myObj=new myConstructor(); myObj.alertName(); </script>
产生一个错误:
因为是一个静态成员。只存在于对象的一个具体实例而不存在于构造函数中。
另外讲一细节,我们平时说下面这两个写法是一样的:
var myConstructor=function(){ } function myConstructor(){ }
但是有一个细节问题,第一种写法必须要先定义才能调用,如果我们先调用在定义,就会报错,而第二种写法不存在这个问题。
添加公有方法:
1、能够使实例化的对象包含的方法称为公有方法,需要修改函数原型,即prototype属性。
2、prototype属性用来定义对象自身内部构造的特殊成员。如果将prototype修改则此修改将立即应用到其派生的对象和实例。
3、当修改一个对象的原型时,任何继承该对象的对象和已经存在的所有实例都回立即继承同样的变化。根据用法的不同这一特性既强大也可能会导致问题,因此当你修改已有的但不是你的对象的原型时要特别小心。
<script type="text/javascript"> function myConstructor(){ //某些代码 this.myMessage="abc"; } var myObj=new myConstructor(); alert(myObj.myMessage); myConstructor.prototype.myName='jh'; alert(myObj.myName); </script>
这就打印出来了abc和jh。
要添加公有方法只需要使用点操作符向它的原型添加方法即可:
添加私有和特权成员:
私有成员就是在构造函数中定义的变量和函数。
例如向myConstructor上添加私有方法和属性只需要:
特权方法:
与私有方法不同,特权方法能够被公开访问,而且还能访问私有成员。特权方法是指在构造函数的作用域中使用this关键字定义的方法:
通过上面的方式myConstructor拥有了和前面使用prototype相同的appendToMessage()方法,但是此时的方法隶属于构造函数的作用域中可以访问私有成员。
公有、私有、特权、静态总结:
1、私有和特权成员在函数的内部,他们会被带到函数的每一个实例中,因而将占用大量的内存。
2、公有的原型成员是对象的蓝图的一部分,适用于通过new关键字实例化该对象的每一个实例。
3、静态成员只适用于对象的一个特殊实例。