主题:  谁能讲讲function()

loveadv

职务:普通成员
等级:3
金币:1.0
发贴:669
#12002/10/26 10:40:07
同上.



s22

职务:版主
等级:4
金币:10.0
发贴:1634
#22002/10/26 14:22:51
function function_name(fuction_arguments){
//code here
}



金山羊

职务:普通成员
等级:4
金币:10.0
发贴:827
#32002/10/27 10:40:23
(1)Flash定义函数大概可以分为三类,第一类是定义普通函数,第二类是定义成员函数,第三类是事件触发函数(注意:function可以定义函数,也可以定义类,要与此分别开来)。
(2)定义普通函数有两种方式,下面我们写一个函数来看看这两种方式:
程序1:
//普通函数1:
//根据两点坐标来计算两点间距离并返回:
function Distance1(c_x0,c_y0,c_x1,c_y1)
{
    var dx = c_x1 - c_x0;
    var dy = c_y1 - c_y0;
    var d = Math.sqrt(dx*dx + dy*dy);
    return d;
}
程序2:
//普通函数2:
//另一种定义方式,作用同上:
Distance2 = function(c_x0,c_y0,c_x1,c_y1)
{
    var dx = c_x1 - c_x0;
    var dy = c_y1 - c_y0;
    var d = Math.sqrt(dx*dx + dy*dy);
    return d;
};
两种方式定义的函数功能是完全相同的,只不过写法上有一些不一样(注意:在Flash 5的环境下,第二种方式会被Flash认为是一个句子,所以会给你缩为一行,不过不影响功能)。这种写函数的方式非常方便,尤其是第二种方式,可以在程序的任何地方写入函数,但是这样写出来的函数要想调用必须写正确路径,要不然不能得到运行。另外就是必须先加载函数然后再进行调用,就是必须先定义函数再调用函数,尤其是当你的函数写在一个MC中却要在外部调用的时候,一定要等到MC加载完成后在调用(在同一帧里Flash是先执行外部程序然后再执行MC内部程序的,所以这时候要注意)。
这两种函数的调用方法相同,都是直接写函数名加上参数就行了,比如我们计算从(0,0)点到(100,100)间的距离的程序:
Distance1(0,0,100,100);
(3)Action Script是面向对象的编程语言,所以Flash支持类的定义及使用,所以Action Script可以定义类的成员函数。这些牵扯到Flash的面相对象化编程,我们将等到后几张再做详细介绍,在这里我们来介绍两个定义函数的方式,它们都属于此类定义方式,不过不是给你自定义类来定义成员函数,这两种函数我们暂时可以认为是全局函数,所谓全局函数就是此类函数不用加路径就可以直接调用(包括在MC中定义后在主Scene下调用)。
程序3:
//成员函数1:
//利用MovieClip定义,作用同上:
MovieClip.prototype.Distance3 = function(c_x0,c_y0,c_x1,c_y1)
{
    var dx = c_x1 - c_x0;
    var dy = c_y1 - c_y0;
    var d = Math.sqrt(dx*dx + dy*dy);
    return d;
}
程序4:
//成员函数2:
//利用Object定义,作用同上:
Object.prototype.Distance4 = function(c_x0,c_y0,c_x1,c_y1)
{
    var dx = c_x1 - c_x0;
    var dy = c_y1 - c_y0;
    var d = Math.sqrt(dx*dx + dy*dy);
    return d;
}
本来类的成员函数是要类的对象才能调用,但是这两种函数可以像普通函数一样调用,其实我们可以把整个Flash的所有Symbol都看作为MovieClip与Object的对象,所以在整个Flash中都可以直接调用。
(4)定义事件触发函数,这是Flash MX新增的功能,可以直接定义MC或按钮的事件触发函数,比如当一个MC或按钮被按到的时候运行。Flash MX增添了这种功能以后使得所有的Action Script可以完全写在时间轴上了,这样对于我们管理我们的程序带来了很大的方便(有关这方面的东西我们以后还将仔细论述)。
我们在以前的程序中也在很多地方用到了事件触发函数,比如我们以前经常用到的:
_root.onEnterFrame = function()
{
    ……
}
就是一个事件触发函数,它相当于onClipEvent (enterFrame)的功能,现在包括键盘事件等在内的所有事件触发功能全部都能写出这种形式的函数。如果你想了解每种事件触发功能请查阅相关资料或Flash帮助。
//源自5d系列图书《flashMx疑难解答百例》(待出版)第七章

编辑历史:[这消息被goldgoat编辑过(编辑时间2002-10-27 10:50:09)]

5d.cn
FLASHDEP
TECHNOLOGY SUPPORT
JAVA/ACTIONSCRIPT/javascript
CFML/JSP/COLDFUSION/FLASH REMOTING
JRUN/COLDFUSIONMX
FLASH/DREAMWEARER

金山羊

职务:普通成员
等级:4
金币:10.0
发贴:827
#42002/10/27 10:44:36
(1)定义类。定义类与定义函数基本上没有什么区别(类不能有返回值),如下面程序:
程序1:
//定义类ClassA:
function ClassA()
{
    this.name = "ClassA";
    trace("This is ClassA.");
};
//定义类ClassB:
ClassB = function(arg)
{
    this.name = "ClassB";
    trace("The ClassB's argument :"+arg);
};
//分别给两个类定义对象,并输出内部变量:
myA = new ClassA();
myB = new ClassB("ClassB's arg");
trace(myA.name);
trace(myB.name);

就像定义函数一样,function的位置并不影响定义的结果,如图87.1是我们程序的运行结果,说明我们定义的类都是成功的。

图87.1 定义类与对象
而如果我们直接那ClassA与ClassB当作函数来调用,那么同样也能输出前面两句,但后面两句没法再输出了。
(2)类的初始化与函数的执行有什么不同。我们定义对象的过程可以看作是类的初始化过程,而我们调用函数却是直接运行程序,那这两种方式有什么不同呢?我们就对一个程序段进行两种调用,看看有什么区别。
//程序2:
ClassA = function(arg)
{
    trace(arg+"'s this :"+this);
    this.name = "ClassA";
};
myA = new ClassA("myA");
trace("this.name = "+this.name);
ClassA("Function");
trace("this.name = "+this.name);

如图87.2就是程序2的运行结果,由结果我们可以看出,当初始化类的时候,类内的this指针指向的是新建的对象本身,而调用函数的时候,this指针指向的却是_root,同样在初始化类后,this.name是新建对象的内部变量,不属于外部MC,而调用函数后,this.name却存在与Scene下面了。

图87.2 类与函数的区别
(3)返回值的问题。我们都知道,Flash中,函数是可以由返回值的,但是类能不能由返回值呢?它返回给谁呢?答案当然是类的初始化不能返回值。请看下面程序3:
//程序3:
ClassA = function(arg0,arg1)
{
    this.total = arg0 + arg1;
    trace(this.total);
    return this.total;
};
myA = new ClassA(10,20);
trace(myA);
myB = ClassA(20,30);
trace(myB);
程序3的运行结果如图87.3所示,我们可以看出,类的初始化没有返回值,而直接调用函数就有返回值。
//源自5d系列图书《flashMx疑难解答百例》(待出版)第十章


5d.cn
FLASHDEP
TECHNOLOGY SUPPORT
JAVA/ACTIONSCRIPT/javascript
CFML/JSP/COLDFUSION/FLASH REMOTING
JRUN/COLDFUSIONMX
FLASH/DREAMWEARER

金山羊

职务:普通成员
等级:4
金币:10.0
发贴:827
#52002/10/27 10:46:43
(1)省略形参怎样读取参数。我们先看看下面这个程序:
程序1:
test = function (arg0, arg1)
{
    trace(arg0+" "+arg1);
    trace(arguments[0]+" "+arguments[1]);
};
test("first", "second");
程序的运行结果如图88.1,

图88.1 程序1运行结果
从结果中我们看出,两个参数的值与arguments数组的元素值是完全一样的(在这里它们不是相等意义的,不指向同一地址),如果我们把arg0与arg1两个形式参数去掉会怎么样呢?其结果与我们预料的完全是相同的,程序仍然输出了两个参数。
(2)省略参数是否适合与类的初始化。验证很简单,我们只要把程序1的最后一句改为
new test("first", "second");
就可以了,这时候我们再运行程序,输出结果仍然是88.1所示,所以对于类的初始化,arguments数组仍然是可用的。
(3)既然arguments是个数组,那么我们就能够读取它的长度,而因此来判断实参的个数了,如下面程序是计算一个数列的平均值的。
程序2:
Average = function()
{
    for(i = 0;i < arguments.length;i++)
    {
        if(typeof(arguments[i]) == "number")
        {
            total += arguments[i];
        }else{
            trace("It's error!");
            total = 0;
            break;
        }
    }
    return total/arguments.length;
};
trace(Average(10,2,34,5));
trace(Average(100,98,76,49,85));
trace(Average(100,"a",11));
如图88.2就是上面这段程序的运行结果,

图88.2 计算数列的平均值
从上面的程序和结果中我们能够看出,arguments数组有时候能为我们提供很大的方便,我们可以很容易的求任意几个数的平均值,而不同的个数不必定义新的函数(当然我们也可以用普通的方法来传递数组,不过注意,我们传递数组是传递地址)。
(4)产生递归。Flash中arguments对象中有一个callee的属性,它代表的是这个函数本身,如果我们在函数中使用它的话,就会产生函数的递归调用。请看下面程序,我们来计算一个整数的阶乘。
程序3:
Factorial = function (x) {
if (x <= 1) {
return 1;
} else {
return x * arguments.callee(x-1);
}
};
trace(Factorial(6));//output 720
因为输出很简单,我们就不再以图形方式列出,不过输出为720说明它的计算是正确的(如果不信,可以再试一试别的数)。在程序中arguments.callee其实就是代表了Factorial本身,这段程序写成下面的样子可以得到同样的效果:
程序4:
Factorial = function (x) {
if (x <= 1) {
return 1;
} else {
return x * Factorial(x-1);
}
};
trace(Factorial(6));//output 720
对于这种方式产生递归,仅限制与函数的定义,对于类的初始化就不再适合,那样会产生混乱。不过其他的方式方法对于函数和类的初始化都是适合的。
//源自5d系列图书《flashMx疑难解答百例》(待出版)第十章


5d.cn
FLASHDEP
TECHNOLOGY SUPPORT
JAVA/ACTIONSCRIPT/javascript
CFML/JSP/COLDFUSION/FLASH REMOTING
JRUN/COLDFUSIONMX
FLASH/DREAMWEARER

金山羊

职务:普通成员
等级:4
金币:10.0
发贴:827
#62002/10/27 10:48:07
有关function的资料还非常多,在flash里面function是非常重要的,尤其是对于高级编程来说,如果想了解更多,请等待5d系列图书出版


5d.cn
FLASHDEP
TECHNOLOGY SUPPORT
JAVA/ACTIONSCRIPT/javascript
CFML/JSP/COLDFUSION/FLASH REMOTING
JRUN/COLDFUSIONMX
FLASH/DREAMWEARER

Demon.S

职务:版主
等级:5
金币:10.0
发贴:2468