Truly
写精彩代码 品暇逸人生
posts - 92,comments - 309,trackbacks - 46
作者:Truly
日期:2007.7.29

上次我们在《在JavaScript中使用面向对象》讨论了对象的声明、成员的声明、全局变量和局部变量以及命名空间的处理。本文继续讨论面向对象,今天介绍方法重载

同时上次有人询问Function对象的apply方法和call方法的区别,本文将一并进行探讨。

首先我们需要知道Javascript有很多语言特点使得我们不能完全按照以往的编程经验进行编程,比如方法重载。在前一篇文章中,我们已经介绍过,在Javascript中后面的同名变量会覆盖前面的,所以想直接声明重载方法是不可行的。但是,Javascript的魅力就在于灵活,因此所有的期望都必然得到答案。

为了节省时间,今天我将所有的代码集中在一起,不再独立讲解,请看如下代码:

<script type='text/javascript'>

function ABC()
{
    
this.member = 1;
    
this.method = Show;
}
function Show(a,b,c)
{
    
this.member = 123;
    
if(arguments.length==1)
        
if(arguments[0].constructor == Number)
            Show1_int.apply(
this, arguments);
        
else if(arguments[0].constructor == Date)
            Show1_date.apply(
this, arguments);
        
else
            Show1_string.apply(
this, arguments);
    
if(arguments.length==2)
        
if(arguments[0].constructor == Array)
            Show3.apply(
this,arguments);
        
else
            Show2.apply(
this,arguments);
}
function Show1_int(a)
{
    alert('
1 integer input parameter ' + a+ '  methode is called');
}
function Show1_string(a)
{
    alert('
1 string input parameter ' + a+ '  methode is called');
}
function Show1_date(a)
{
    alert('
1 date input parameter ' + a+ '  methode is called');
}

function Show2(a,b)
{
    alert('
2 input parameter is transfer:\na:'+a+'\nb:'++ '\nthe member is' + this.member);
}
// 演示引用方式传递
function Show3(a,b)
{
    arguments[
0][0]=2;
    alert('
2 input parameter is transfer:\na:'+a+'\nb:'++ '\nthe member is' + this.member);
}
var o = new ABC();
var arr = new Array();
arr[
0]=321;
o.method(arr[
0],2);    // 值传递
alert(arr[0]);        // 原始值未改变
o.method(arr,2);    // 引用方式传递
alert(arr[0]);        // 方法调用时被方法修改
o.method(new Date());

</script>


我们无法直接定义重载方法,但是却可以为其他函数定义一个公开的重载方法调用。通过这种方式,对于调用者而言,重载的方法是透明的,只需调用方法名并传入适当的参数即可,与多数高级语言一样,不可定义传入参数相同而返回类型不同的重载方法。

下面我们再分析一下callapply的区别,所有的函数都具有这两个方法,它们在使用上没有太大差别,主要区别就在于传入参数不同:

call使用可变参数序列进行值传递,而apply则使用数组或者arguments对象进行传递。

call方法的语法:
call([thisObj[,arg1[, arg2[,   [,.argN]]]]])

参数
thisObj 
可选项。将被用作当前对象的对象。 
arg1, arg2, , argN 
可选项。将被传递方法参数序列。 
说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法的语法:
apply([thisObj[,argArray]])

参数
thisObj 
可选项。将被用作当前对象的对象。 
argArray 
可选项。将被传递给该函数的参数数组。 
说明
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

注:以上资料来自《Jscript参考手册》

小节:通过show2方法,我们看到使用call或者apply方式可以将当前对象传递到方法内部,以此来访问当前对象的一些成员。这使得我们可以定义一些方法,给不同的自定义类进行调用,具体可以查看上篇文章我们定义的一个继承结构。

同时通过上面例子我们还演示了两者进行传递时,参数的传递方式会根据参数的不同而不同,如果是值变量则使用值传递,否则以引用方式传递。

尾声:当我们使用JavaScript的时候,你必须了解和掌握JavaScript的一些特点,它跟高级编程语言存在着一些区别,它灵活的特点给我们的开发带来了极大的灵活性,因此一旦深入JavaScript编程,我保证,你会毫无理由的喜欢上它。


posted on 2007-07-29 13:20 Truly 阅读(3039) 评论(12)  编辑 收藏 所属分类: JavaScript & Vbscript

FeedBack:
2007-07-29 14:01 | Hurry [未注册用户]
重载好麻烦,不如换函数名了
  回复  引用    
#2楼 [楼主]
2007-07-29 14:09 | Truly      
呵呵,没有办法。不过这样以来还是有些好处的,把你重命名的函数都整理到一个公共接口,这样对于编写类库给别人调用的话,还是极大的方便了调用者,不用再去记一堆方法名了。
  回复  引用  查看    
2007-07-29 15:05 | 曲滨*銘龘鶽      
@Truly

javaScript 子类 在重写基础类 函数的时候

能否调用基础类的函数如

我有一个 A 类,有一个 toString 函数

B 继承 A 重写 toString

但在 B 的toString 中要调用 A 的 toString

能否实现。
  回复  引用  查看    
#4楼 [楼主]
2007-07-29 18:32 | Truly      
通常我们的类继承是通过prototype实现的,由于prototype的特点,我们一旦在继承类中定义了基类的方法,就无法得到基类的这个方法了。如果强制访问,只会造成死循环直至堆栈溢出。这个在msdn的文章中已经说明了,可见http://msdn.microsoft.com/msdnmag/issues/07/05/JavaScript/default.aspx?loc=zh
注意以下文字:

继承原型对象的对象上可以立即呈现对原型所做的更改,即使是在创建这些对象之后。
如果在对象中定义了属性/方法 X,则该对象的原型中将隐藏同名的属性/方法。例如,通过在 Dog.prototype 中定义 toString 方法,可以改写 Object.prototype 的 toString 方法。
更改只沿一个方向传递,即从原型到它的派生对象,但不能沿相反方向传递。

因此你的这个要求无法直接实现。
  回复  引用  查看    
2007-07-30 17:14 | 镜涛      
感觉直接定义不同名函数比较方便,这样的重载方法不知道是不是值得!
  回复  引用  查看    
2007-07-30 17:14 | 镜涛      
感觉直接定义不同名函数比较方便,这样的重载方法不知道是不是值得!
  回复  引用  查看    
2007-07-30 17:15 | 镜涛      
感觉直接定义不同名函数比较方便,这样的重载方法不知道是不是值得!
  回复  引用  查看    
2008-06-04 12:14 | 独孤酒间 [未注册用户]
无聊的做法。。直接在一个方法里判断参数类型及是否为空或未定义就行了 整那么麻烦 不认为很无聊吗??
  回复  引用    
#9楼 [楼主]
2008-06-04 13:02 | <font color=red>Truly</font>      
to: 独孤酒间
虽然可以通过类型和arguments来处理,但是违背了面向对象的原则,请问这样定义出来的还是符合面向对象的原则吗?


  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: