JavaScript 面向对象

(1)在JavaScript中,每个对象可以看作是多个属性(方法)的集合,引用一个属性(方法)很简单,即:对象名.属性(方法)名。除此之外,还可以用方括号的形式来引用:对象名[“属性(方法)名”]注意,这里的方法名和属性名是一个字符串,而非原先点号后面的标识符,当对象的属性存在数字开头或中间有空格的情况时 就需要用[]的形式,一定程度上利用了""的转义

(2)动态添加、删除、修改对象及属性,下面的例子中就在空对象user上添加了alert方法和name属性

    var user=new Object();
    user.alert=function(){alert(“my name is:”+this.name);}
    user.name=”jack”;

(3)提供了另外一种简单的方式来创建无类型对象,这种对象无明显类的概念,只是一大堆属性和方法的集合,即大括号({})语法:
{property1:statement,property2:statement2,…,propertyN:statmentN}通过大括号括住多个属性或方法及其定义(这些属性或方法用逗号隔开),来实现对象的定义,这段代码就直接定义个了具有n个属性或方法的对象,其中属性名和其定义之间用冒号(:)隔开。如

var user={
   name:"jack", //定义了name属性,初始化为jack
   favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
   hello:function(){ //定义了方法hello
   alert("hello,"+this.name);},                  
   sex:"male" //定义了性别属性sex,初始化为sex
  }

(4)Prototype对象

prototype 对象是实现面向对象的一个重要机制。每个函数(function)其实也是一个对象,它们对应的类是“Function”,但它们身份特殊,每个函数对象都具有一个子对象prototype。顾名思义,prototype 表示了该函数的原型,而函数也即是类,prototype 实际上就是表示了一个类的成员的集合。当通过new 来获取一个类的对象时,prototype 对象的成员都会成为实例化对象的成员。既然prototype 是一个对象,可以使用前面两节介绍的方法对其进行动态的修改。注意通过prototype这种方式增加的方法,在new 对象的时候,新对象会自动增加这些属性或方法。(2)中所述的动态增加修改的属性及方法只对于对象来说的,不是类的概念。

(5)Function对象

在JavaScript中,函数对象对应的类型是Function,正如数组对象对应的类型是Array,日期对象对应的类型是Date一样,可以通过new Function()来创建一个函数对象,也可以通过function关键字来创建一个对象。function funcName(){}等价于var funcName=function(){}。但前面一种方式创建的是有名函数,而后面是创建了一个无名函数,只是让一个变量指向了这个无名函数。在使用上仅有一点区别,就是:对于有名函数,它可以出现在调用之后再定义;而对于无名函数,它必须是在调用之前就已经定义。

(6)除了函数对象,还有很多内部对象,比如:Object、Array、Date、RegExp、Math、Error。更准确的说,这些名称实际上表示一个类型,可以通过new 操作符返回一个对象。然而函数对象和其它对象不同,当用typeof 得到一个函数对象的类型时,它仍然会返回字符串 “function”,而typeof一个数组对象或其它的对象时,它会返回字符串“object”。下面的代码示例了typeof不同类型的情况:
alert(typeof(Function)));
alert(typeof(new Function()));
alert(typeof(Array));
alert(typeof(Object));
alert(typeof(new Array()));
alert(typeof(new Date()));
alert(typeof(new Object()));
运行这段代码可以发现:前面4 条语句都会显示“function”,而后面3 条语句则显示“object”,可见new一个function实际上是返回一个函数。

(7)JavaScript为函数对象定义了两个方法:apply和call,它们的作用都是将函数绑定到另外一个对象上去运行,两者仅在定义参数的方式有所区别:Function.prototype.apply(thisArg,argArray);   Function.prototype.call(thisArg[,arg1[,arg2…]]);
从函数原型可以看到,第一个参数都被取名为thisArg,也就是说,所有函数内部的this指针都会被赋值为thisArg,这就达到了将函数作为另外一个对象的方法运行的目的。两个方法除了thisArg 参数,都是为Function 对象传递的参数。

    JavaScript 中的this 指针是一个动态变化的变量,它表明了当前运行该函数的对象。由this指针的性质,也可以更好的理解JavaScript中对象的本质:一个对象就是由一个或多个属性(方法)组成的集合。每个集合元素不是仅能属于一个集合,而是可以动态的属于多个集合。这样,一个方法(集合元素)由谁调用,this指针就指向谁。实际上,前面介绍的apply方法和call方法都是通过强制改变this指针的值来实现的,使this指针指向参数所指定的对象,从而达到将一个对象的方法作为另一个对象的方法运行的效果。

(8)在JavaScript中可以使用function关键字来定义一个“类”。现在介绍如何为类添加成员。其过程很简单,在函数内通过this指针引用的变量或者方法都会成为类的成员,

function class1(){
var s=”abc”;
this.p1=s;
this.method1=function(){
alert(“this is a test method”);}
}

var obj1=new class1();当通过new class1()获得对象obj1 时,这个对象便自动获得了属性p1和方法method1。注意只有用this指向的属性和方法才会被赋予对象,至此已经有多种方法可以为对象添加属性或方法了,如通过prototype的原型添加,还有在对象本身动态添加,这里的通过this将function中的this指向的给与对象。

(9)前面介绍了如何定义一个类,如何初始化一个类的实例,但既可以在function定义的函数体中添加成员,又可以用prototype 定义类的成员,代码显的很混乱,和面向对象语言类的实现之间有着很大的区别。那么,如何以一种清晰的方式来定义类呢?下面给出了一种类的实现模式,并将它们对应到面向对象语言类的实现上。。而在JavaScript中,由于对象的灵活的性质,在构造函数中也可以为类添加成员,在增加灵活性的同时,也增加了代码的复杂度。为了提高代码的可读性和开发效率,完全可以抛弃这种定义成员的方式,而使用prototype 对象来替代,这样function 的定义就类的构造函数,符合传统意义类的实现:类名和构造函数名是相同的。

function class1(){//构造函数
}
//成员定义
class1.prototype.someProperty=”sample”;
class1.prototype.someMethod=function(){方法实现代码
}

虽然上面的代码对于类的定义已经清晰了很多,每定义一个属性或方法,都需要使用一次class1.prototype,不仅代码体积变大,而且易读性还不够。为了进一步改进,可以使用无类型对象的构造方法来指定prototype对象,从而实现类的成员定义:

//定义一个类class1
function class1(){//构造函数
}
//通过指定prototype对象来实现类的成员定义
class1.prototype={
someProperty:”sample”,
someMethod:function(){//方法代码
},
…//其他属性和方法.
}

上面的代码用一种很清晰的方式定义了class1,构造函数直接用类名来实现,而成员使用无类型对象来定义,以列表的方式实现了所有属性和方法,并且可以在定义的同时初始化属性的值。这也更类似于传统意义面向对象语言中类的实现。只是构造函数和类的成员定义被分为了两个部分,不妨将其看成JavaScript中定义类的一种固定模式,这样在使用时会更加容易理解。

      在一个类的成员之间互相引用,必须通过this 指针来进行,例如在上面例子中的someMethod 方法中,如果要使用属性someProperty,必须通过this.someProperty的形式,因为在JavaScript中每个属性和方法都是独立的,它们通过this指针联系在一个对象上。

(11)私有成员即在类的内部实现中可以共享的成员,但是并不对外公开。JavaScript 中并没有特殊的机制来定义私有成员,但可以用一些技巧来实现这个功能。这个技巧主要是通过变量的作用域性质来实现的,在JavaScript中,一个函数内部定义的变量称为局部变量,该变量不能够被函数外的程序所访问,却可以被函数内部定义的嵌套函数所访问。在实现私有成员的过程中,正是利用了这一性质。  如果属性及方法无this修饰即为局部变量。

    

 function class1(){
   var pp=" this is a private property"; //私有属性成员pp
   function pm(){ //私有方法成员pm,显示pp的值
   alert(pp);
}
this.method1=function(){ //在公有成员中改变私有属性的值
   pp="pp has been changed";
}
this.method2=function(){
    pm(); //在公有成员中调用私有方法
 }
}
var obj1=new class1();
obj1.method1(); //调用公有方法method1
obj1.method2(); //调用公有方法method2

(12)和私有成员的勉强相比,静态成员则显得“正统”的多。静态成员即属于一个类的成员,
它可以通过“类名.静态成员名”的方式访问。在JavaScript中,可以给一个函数对象直接添
加成员来实现静态成员,因为函数也是一个对象,所以对象的相关操作,对函数同样适用。
例如:

function class1(){//构造函数
 }
//静态属性
class1.staticProperty=”sample”;
//静态方法
class1.staticMethod=function(){
    alert(class1.staticProperty);
}
//调用静态方法
class1.staticMethod();


通过上面的代码,就为类class1 添加了一个静态属性和静态方法,并且在静态方法中引用了该类的静态属性。

通过Function 的prototype 原型对象,可以给任何函数都加上通用的静态成员,这在实际开发中可以起到很大的作用,

(13)用for(...in...)实现反射机制

这里var p表示声明的一个变量,用以存储对象obj的属性(方法)名称,有了对象名和属性(方法)名,就可以使用方括号语法来调用一个对象的属性(方法):

for(var p in obj){
   if(typeof(obj[p]==”function”){
      obj[p]();
   }else{
      alert(obj[p]);
   }
}

这段语句就遍历obj对象的所有属性和方法,遇到属性则弹出它的值,遇到方法则立刻执行。该语句就是遍历一个集合内的所有成员。在后面可以看到,在面向对象的JavaScript
程序设计中,反射机制是很重要的一种技术,它在实现类的继承中发挥了很大的作用

(14)利用反射机制来实现类的继承,思路如下:利用for(…in…)语句枚举出所有基类prototype的成员,并将其赋值给子类的prototype对象。

<script language="JavaScript" type="text/javascript">
<!--
function class1(){
//构造函数
}
class1.prototype={
   method:function(){
   alert(1);
},
method2:function(){
   alert("method2");
}
}
function class2(){
//构造函数
}
//让class2继承于class1
for(var p in class1.prototype){
    class2.prototype[p]=class1.prototype[p];
}
//覆盖定义class1中的method方法
class2.prototype.method=function(){
    alert(2);
}
//创建两个类的实例
var obj1=new class1();
var obj2=new class2();
//分别调用obj1和obj2的method方法
obj1.method();
obj2.method();
//分别调用obj1和obj2的method2方法
obj1.method2();
obj2.method2();
//-->
</script>

从运行结果可见,obj2 中重复定义的method 已经覆盖了继承的method 方法,同时method2方法未受影响。而且obj1 中的method方法仍然保持了原有的定义。这样,就实现了正确意义的类的继承。为了方便开发,可以为每个类添加一个共有的方法,用以实现类的继承:
//为类添加静态方法inherit表示继承于某类

Function.prototype.inherit=function(baseClass){
   for(var p in baseClass.prototype){
     this.prototype[p]=baseClass.prototype[p]; 
   }
}
这里使用所有函数对象(类)的共同类Function 来添加继承方法,这样所有的类都会
有一个inherit方法,用以实现继承,读者可以仔细理解这种用法。于是,上面代码中的:
//让class2继承于class1
for(var p in class1.prototype){
class2.prototype[p]=class1.prototype[p];
}
可以写为:
//让class2继承于class1
class2.inherit(class1)
这样代码逻辑变的更加清楚,也更容易理解。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值