Flash入门教程深入理解函数郑州清新教育提供.doc_第1页
Flash入门教程深入理解函数郑州清新教育提供.doc_第2页
Flash入门教程深入理解函数郑州清新教育提供.doc_第3页
Flash入门教程深入理解函数郑州清新教育提供.doc_第4页
Flash入门教程深入理解函数郑州清新教育提供.doc_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

理解函数的目的给函数传递参数理解函数的变量作用域的重要性编写自定义函数从函数返回值用setInterval()创建递归函数通过使用函数,就可以创建可重用的代码、可读的代码、灵巧的代码。有了函数,就可以写出有效的、结构精巧的、维护得很好的代码,而不是冗长的、笨拙的代码。一、理解用函数进行编程函数是一种革新。写代码没有函数,就像出版图书没有印刷机,出版业是如此没有生产力,如此没产量。有了印刷机,只制一次版,就可以从那个版复制出许多副本了。印刷机是一种革新。同样地,如果编程序没有函数,就不得不一次一次地写出代码的每一行。但是,当写出一个函数时,就可以将多条语句封装在一起,就可以重复地调用那个函数(即那些语句的组),而不用重复写相同的代码了。那就巧妙多了。函数是一种组织起一个代码块的方法,该代码块直到从其主流程中调用(直接地或间接地)时才执行。换句话说,函数是一种将调用时才执行(不调用不执行)某个特殊任务的代码块包装在一起的方法。函数比非结构化编程更具优势。这些优势包括: 通过消除混乱和冗余的代码,使代码更具有可读性。 通过重复使用函数而不是每次重复输入整个代码块,使程序更加有效率。 函数成为了进行修改的中心点。在函数中做个修改,该修改就能被应用到每个调用该函数的实例中。 编写成熟的函数可以在许多程序中重复使用。因此,可以开发出一个可被用于建立各种程序的函数库,而不需要每次从打草稿开始写脚本。 包装在一个函数中的代码提供了进行用户交互的基础。如果没有函数,应用程序就像一个单独的程序那样运行。有了函数,一个用户发起的动作就可以调用一个函数。 二、定义自定义函数 我们已经知道在ActtionScript代码中使用函数的某些优点了。现在,需要学习如何来写函数。写一个函数也被称为“定义”或“声明”一个函数。函数的语法: function 函数名(参数):返回数据类型 函数体 ) 在函数的语法中,要注意如下几个关键点:function关键字告诉Flash,正在声明一个函数。当定义一个函数时,必须像上面那样包括function关键字。函数应该遵守变量的命名规则。就像命名变量那样,给函数取一个能表示其功能的名字是一个好想法。所有函数的定义都必须在函数名字后面包括一对圆括号。在圆括号中的“参数”可以没有。在后面可以读到有关参数的更详细的内容。但是,无论一个函数是否定义了参数,都必须在定义中包括一对圆括号。圆括号后面接着就是冒号和一个有效的数据类型名字。数据类型是函数将返回的数据的类型。在后面会看到如何返回数据。使用Void表示该函数不返回值。函数体是由一对开始和结束波浪式大括号()定义的。现在已经知道基本的语法了,那就看一个非常简单的函数例子吧: function displayGreeting():Void trace(Hello.); 三、调用函数我们将术语“函数”定义为延迟执行的代码块。这就是说,一个函数可以被定义,但直到访问或调用它之前什么也不会发生。可以自己测试一下这一点,即在主时间轴的第1帧中,用如下代码创建一个新的Flash影片: function displayGreeting():Void trace(Hello.); 当测试该影片时会看到,尽管在代码中有一个trace()动作,但什么也没发生。所以,既然知道了如何“定义”函数,就需要学习如何通过“调用”它们而在程序中使用它们。为了调用一个函数,需要使用该函数的名字,并后跟一个圆括号(它被称为“函数调用运算符”)。当调用一个函数时,对函数的调用本身就是一个语句。因此,应该在该语句的后面使用一个分号。下面的例子定义了一个函数,然后调用它。如果想自己学习和测试它,只需将该代码放置在主时间轴的第1帧即可。 function displayGreeting():Void trace(Hello.); displayGreeting();/调用函数 当测试该影片时,在Output窗口中显示如下内容:Hello. 四、传递参数某些函数不需要给它们传递任何信息。例如,前面一节中的dlsplayGreetlng()函数就不需要任何参数。换句话说,许多函数需要给它们传递参数。例如,如果dlsplayGreetlng()函数可以使用不同的姓名来显示个性化的问候,就会使dlspayGreetlng()函数更加有趣了。有了参数,实现这一点就简单了。把上面的函数修改一下,如下所示: function displayGreeting(姓名:String):Void trace(Hello.+姓名) 一旦用这种方式定义了该函数,就可以调用它了,并给它传递不同的参数值。某些例子如下所示:displayGreeting(张三);/显示:Hello.张三displayGreeting(李四);/显示:Hello.李四在一个函数中,一个参数就是一个变量,当调用该函数时就给变量赋值。就像在displayGreeting()函数中所看到的那样,参数被命名为姓名,在每次调用该函数的时候就给该参数设置值。当用值张三调用该函数时,该变量就被赋予了张三;当用值李四调用该函数时,该变量就被赋予了李四。参数(变量)是在函数定义的圆括号中声明的。读者可能注意到了,参数的声明与常规变量的声明相似但略微不同。首先,声明的相似性在于,需要给变量创建一个名字并定义一个数据类型。但是,当声明一个参数时,不需要使用var关键字,也不需要使用分号,并且不能在圆括号中初始化一个参数。下面的代码是不正确地声明参数的例子,将产生错误: /不能使用var关键字。 function displayGreeting(var 姓名:String):Void trace(Hello.+姓名) /不能使用分号。 function displayGreeting(姓名:String;):Void trace(Hello.+姓名) /不要试着在圆括号中初始化变量。 function displayGreeting(姓名:String=王麻子):Void trace(Hello.+姓名) 如果想在函数中使用多个参数,该怎么办呢?很简单,当定义函数时,可以声明用逗号分隔开的多个参数。同样地,当调用该函数时,可以给它传递多个值,只需简单地用逗号分隔这些值即可。如下是具有多个参数的dlspayGreetlng()函数的例子: function displayGreeting(姓名:String,体重:Number):Void trace(姓名+的体重是:+体重); displayGreeting(张三,50);/显示:张三的体重是:50 ,读者可能注意到了,当开始将越来越多的参数添加到一个函数定义的参数列表中时,代码就开始超出编辑器的边界了。可以在Actions面板中启用自动换行功能。还可以在定义函数时将每个参数(或参数组)放置到新的一行中。这是一个通常采用的习惯,因为它能更容易地阅读一个由许多参数组成的函数的参数列表。语法是相同的,区别仅在于:参数列表中的每个参数都放在新的一行中,以便使它更容易阅读。例如: function displayGreeting(姓名:String, 体重:Number):Void trace(姓名+的体重是:+体重); 注意:定义函数的参数个数与调用时传递的参数个数不一定要相同,当然,如果该有的参数没有的话,可能函数不会正常工作,多个参数是按先后顺序依次“对号入座”的。1、给参数传递值和引用。当给函数传递参数时,参数是用两种方式之一进行传递的:按值和按引用。其区别与数据类型有关。(1)基本数据类型,如string,number,Boolean,是按值传递的。这就是说,值被传递给了函数,而与该值所来自的变量的任何联系都被切断了。换句话说,当值被传递给函数后,任何被用于传递值的变量就独立了。下面是一个例子: function 引用测试(a:Number):Number a+; return a; var b:Number=5; var c:Number=引用测试(b); trace(b); trace(c); Output窗口会显示如下内容 5 6在这个例子中,尽管b的值被传递给了函数,并且那个值在函数中被增加了1,但b仍保持它的值(5)。为什么?因为b的值被传递给了函数,而不是变量自己。然后,那个值在函数中被赋予了一个名为a的参数,被增加、被返回。然后,返回的值被赋予了一个新的名为c的变量。(2)当引用数据类型被作为参数传递时,它们就按引用进行传递。这就是说,一个被传递给函数的对象是对该实际对象的一个引用。其结果是,在函数中对对象引用所做的任何事情都会影响到该对象本身。没有产生该对象的副本。下面是一个使用名为mBox的MovieClip实例的例子: function move(mA:MovieClip,X:Number,Y:Number):Void mA._X=x; mA._y=y; move(mBox,100,100); 上面这个例子将名为mBox的MovieClip对象移动到舞台的(100,100)处。 2、使用arguments属性。现在所看见过的函数要么不使用任何参数,要么参数被声明为圆括号中的参数列表。但是,不管一个函数是否声明了任何参数,传递给函数的所有参数都被保存在一个名为arguments的特殊数组中。每个函数都有一个arguments变量(对象),当调用函数的时候,就在该函数中创建该变量。ActionScript并不强求函数定义中的参数个数与调用时传递给该函数的参数个数一致。其意思是在调用时没有被传递、但在函数的参数字符串中被定义过的任何值,都会具有一个undeflned值;而在函数调用中传递的任何值,如果在函数的参数定义中没有它,就会被忽略。因此,完全可以定义一个没有参数的函数,但仍然可使用arguments对象传递参数。下面是一个把arguments对象作为数组使用的例子: function traceParams():Void for(i=0;i0) return nOperand * arguments.callee(nOperand-1); else return 1; 五、从函数返回一个值到现在为止,主要介绍了函数作为子程序的这一点。也就是说,函数可以将主程序分解为更小的、更易管理的片段。一方面,当函数用那种方式作为一个子程序时,函数并不需要返回一个值。另一方面,某些时候想创建一个函数,用它进行某些计算或操作,然后返回一个值。可以在一个函数中使用return语句来返回一个特定的值。return语句的语法如下所示: return value;当使用return语句从一个函数返回一个值时,应该指定要被返回的数据类型(在函数定义的圆括号后面指定)。在此之前的例子中,返回类型是Void(表示无返回)。但是,当返回一个字符串时,就应该将返回的数据类型设置成String;当返回一个数字时,就应该将返回的数据类型设置成Number,等等。下面是一个计算矩形面积的函数的例子,其返回值是数字: function 求面积(nA:Number,nB:Number):Number var nArea:Number=nA * nB; return nArea; 只要遇到return语句,Flash就退出该函数。因此,如果在return语句后面还有其他剩余代码,就不会再执行它们了。例如: function 求面积(nA:Number,nB:Number):Number var nArea:Number=nA * nB; return nArea; trace(The area is:+nArea); 求面积(6,6);在上面的例子中,trace()语句总是不会被执行的。这是因为在函数中的return语句后面的代码是执行不到的。下面是一个使用几个return语句的例子。明显地,在任何对该函数的调用中,只可能遇到其中的一个return语句。而在这个例子中,一个return语句是在条件满足时遇到的,其他return语句是在条件不满足时遇到的。该函数接受两个参数:一个(字符串)数组、一个字符串值。该函数用一个for语句来搜索遍历该数组,直到遇到一个与该字符串匹配的成员为止。一旦发现匹配,它就返回相应的索引。如果没有发现匹配,该函数就返回null。 function findMatchingIndex(aTitles:Array,sTitle:String):Number /循环遍历数组中的所有成员。 for(var i:Number=0;i18) trace(The area is more than 18.); 注意:函数的返回“值”不但可以是数值,字串等,也可以是对象,如数组、Object等。 六、引用函数可以用函数的名字来引用一个函数。当将函数名与函数调用运算符(圆括号)结合起来使用时,函数就被调用了,但是名字本身只是作为对函数的引用。这就是说,实际上可以使用函数的名字来将一个引用赋予一个变量。例如,一旦将对一个函数的引用赋予给一个变量,就可以将那个变量名与函数调用运算符结合起来调用那个函数。下面是一个例子: function 求面积(nA:Number,nB:Number):Number var nArea:Number=nA * nB; return nArea; var fArea:Function=求面积; trece(fArea(6,6);/36 下面将看到如何将匿名函数赋予变量。七、创建匿名函数现在已经知道如何使用标准的、命名的函数语法来定义函数了。除此之外,还有一种使用“匿名函数”来定义函数的方式,它允许创建一个没有名字的函数。然后,可以将该函数赋予一个变量。下面是匿名函数的语法: function(参数):返回类型 函数体 ; 读者可能注意到了,标准的函数声明和匿名函数声明在语法上很相似,仅有两点不同。第一,匿名函数没有函数名。第二,匿名函数后应该跟一个分号,这在标准函数的声明中是不需要的。正如前面所述,这主要是想将匿名函数赋予一个变量。否则,当该函数被定义之后,它就“离开了”作用域(即变成未定义的了)。下面是将匿名函数赋予一个变量的例子: var fSayHi:Function=function(sName:String):Void trace(Hi,+sName); ); fSayHi(Joey);/显示:Hi,Joey 就像所看到的那样,可以使用被赋予该匿名函数的变量来调用该匿名函数。实际上,匿名函数大家经常都在用,回想一下,按钮事件函数的写法,如: btn.onPress=funceton() . 八、理解作用域“作用域”是在ActionScript中定义的某些标识符的作用范围。有些标识符仅在一个时间轴中被定义,有些标识符在整个影片的范围中被定义,有些标识符仅在一个函数中被定义。在函数中,有两种作用域需要解释一下:变量的作用域、函数的作用域。“变量的作用域”是变量在一个函数中的作用范围,“函数的作用域”是一个函数在一个影片中的作用范围。1、变量的作用域当在一个函数中适当地声明一个变量时,该变量就被称为“本地变量”。本地变量表示当在一个函数中声明一个变量时,它的定义在该函数调用之后就不再保留。这是一种避免与其他变量产生命名冲突的好方法。下面是一个函数的例子,它声明并初始化了一个名为sMessage的本地变量。该本地变量在该函数中被定义。但是,如果想使用trace()在该函数之外来显示该变量的值,结果将是未定义的。 function testScope():Void var sMessage:String=hello,world!; testScope(); trace(sMessage);/显示:undefined 在一个具有许多函数的大程序中,使用本地变量有利于确保减少具有相同名字的变量之间的冲突。尽管总是应该试图为变量取一个惟一的名字,但是在不同的函数中重复使用相同的变量名字还是可能的。如果每个都有相同的作用域,那么一个就会干扰另一个,就会导致不希望的值和结果。另一个使用本地变量的可能原因是用于内存管理。尽管它可能并不是真的很大,但在程序中定义的每个变量都会占用内存。如果不用一个变量做什么事了,但它仍被定义,就会浪费内存。通过使用本地变量,当函数结束之后内存就会被释放。参数被看做本地变量,即其作用域在该函数中,但不在它之外。从下面的例子就可以看出这一点: function testParameterScope(sMessage:String):Void trace(sMessage); testParameterScope(Hello); /显示:Hello trace(sMessage);/显示:undefined 与此不同的是,在该函数外面声明的变量(但在定义该函数的相同时间轴中)是可以在该函数中使用的,例如: function testScopeTimeline():Void trace(sMessage); Var sMessage:String=Hello; testScopeTimeline();/显示:Hello 在该例子中,变量sMessage是在该函数之外声明的,但仍可以在该函数之中使用。九、函数的作用域正如现在所知,当声明一个函数时,其作用域被限制在声明它的时间轴中。这就是说,可以通过它的名字在相同的时间轴中调用它;如果使用一个目标路径,那么就可以在那个时间轴之外调用它。在相同的时间轴中使用该函数,是非常容易的。在另一个时间轴中使用该函数,就有些不方便了。在一个没有时间轴的对象中使用该函数,就变得颇具挑战性了。试一试吧!十、创建递归“递归”是指一个函数在其函数体中调用它自己。在某些情况下,这是一种必需的方法。递归的经典例子是计算一个数的阶乘。作为复习,数n的阶乘是指如下公式:n*(n-1)*(n-2) *1 例如,5的阶乘是120(即5*4*3*2*1)。下面就是一个完成这一工作的函数: function factorial(n:Number):Number if(nO) return n*factorial(n-1); else return 1; 递归是一个相当简单的概念,但对于还没有写过大量代码的人来说它又是一个头痛的概念。因此,有些时候它可能有些模糊。为了搞清该例子中的递归的工作原理,我们来看看当调用该函数时会发生什么。这次,我们使用一个小数字来使其简单些:trace(factorial(3);当第一次调用factorial()函数时,是用3这个值进行调用的。因为n大于0,所以它执行if语句中的语句。该语句指示函数返回表达式n*factorial(n-1)的值。为了计算该表达式,该函数必须调用它自己(factorial(n-1)。这一次,当调用factorial()时,是用2这个值进行调用的。同样,n的值大干0,所以执行第一个rettIrn语句。该函数再一次调用它自己。这一次,是用1这个值进行调用的。重复相同的处理,再一次用O这个值调用factorial()。然而,在这次函数调用时,因为n不再大于0了,所以返回1并且不再调用该函数了。应该非常小心,以确保递归函数在递归的次数上有一个限制。设想一下,如果这个例子的函数被写成下面这样,将会发生什么: function factorial(n:Number):Number return n*factorial(n-1); 该函数将永远地调用它自己。这个无限循环往往会导致系统崩溃。幸运的是,Flash对此有一个保护措施,即在一个设定的递归次数之后,会在影片中禁止ActionScript。如果在影片中使用了这种无限递归(即没有一个条件能使该递归停止)的函数,当测试影片时就会在Output窗口中看到警告信息。 十一、重载函数重载函数是指,使多个函数具有相同的名字但具有不同数量和或类型的参数。在许多情况下这可能是有用的。例如,可能有一个名为caIculateArea()的函数,它基于两个参数(各个边的长度)来计算矩形的面积。但可能还希望有一个calculateArea()函数,它基于一个单独的参数(半径)来计算圆的面积。问题是,正如已经提到过的那样,ActionScript并不要求函数定义中的参数数量与传递给它的参数的数量一致。这就是说,不能有两个具有相同名字的函数,即便它们有不同数量的参数。因此,不能真的用ActionScript来重载函数。相反,可以在函数中使用if语句或switch语句来检查参数的数量而模仿函数的重载。下面是一个例子,它说明可以如何写一个函数,使其根据传递给它的参数的数量(由arguments.length决定)计算矩形的面积或者圆的面积。这并不是一个严格意义上的重载函数,而是ActionScript的等价物。 function calculateArea():Number switch(arguments.length) case 1: var nRadius:Number=argumentsO; return(Math.PI*(nRadius*nRadius); case 2: var nA:Number=argumentsO; var nB:Number=arguments1; return(nA*nB); default: return null; 十二、为可重用而编写函数当写一个函数时,要记住易用的或可重用的代码的重要性。理想的情况是使函数尽可能地通用和尽可能地包装好。函数一般应该像一个黑箱一样进行操作。这就是说,函数的活动性从本质上讲应该是不依赖于程序的其他部分的。一个写得很好的函数应该可以被用到许多不同的程序中,就像一把万能钥匙可以开不同的锁一样。应该用可重用性的观念来写函数。当写通用函数时,要记住如下几点:通常,不要使用在函数外面定义的变量在函数中使用的变量(和对象)应该是在函数中声明的或作为参数传递给函数的。如果需要将一个值赋予一个将在函数的作用域之外使用的变量,则考虑使用一个return语句来代替。因为一个函数一次仅能返回一个值,所以可能会发现用一个return语句似乎有点局限。如果在函数中的确是这样的话,那么也许就会发生下面两件事之一:要么想返回的值是相关的值,那么可以将它们放入一个数组或一个对象中,然后返回它们;要么它们是不相关的值,那么就应该将函数拆散成多个函数。但也可能有例外。某些时候,只想用一个函数将一个影片中的某些功能组织到一起,以便将代码组织成子程序。在这种情况下,直接访问在该函数外面声明的变量和对象还是可以接受的。给函数取一个能描述其任务的名字当再次看到函数时,就可以很容易地知道该函数是干什么的了。如果因为函数要做许多事情而不好给它取名,请考虑将那个函数拆散成多个函数。即便是通用函数,它们也应该执行特定的任务。虽然这些指导方针通常是有用的,但有的时候它完全不适合写一个真正通用的函数。如果写一个函数的任务对正在写的程序来说非常特殊,那么将它写得太通用了也许并没什么用。十三、使用内置函数前面已经学过如何在ActionScript中创建一个自定义函数了。通常,当人们谈到函数时所指的就是这些自定义函数。但是,在ActionScript中还有许多其他“内置函数”,基本上可以像使用自定义函数那样来使用它们。Actions工具箱中包含一个名为Global Functions的文件夹,在这个文件夹中是包含所有内置函数的子文件夹。这些函数中的许多已经被类和方法代替了,因此最好使用这些新的替代品。例如,所有的时间轴控制、影片剪辑控制和打印函数都已经被方法代替了。但仍有某些全局的内置函数是有用的。这些函数包括:fscommand()_一仅在非常特殊的情况下才使用这个函数。fscommand()函数能使Flash影片与播放器进行通信。setInterval()/clearInterval()这些函数能够指示Flash按特定的、固定的间隔去调用其他函数。请参见下面的“创建间隔函数”中的详细内容。escape()/unescape()这些函数被用于在文本和安全URL格式之间进行转换。getTimer()getTimer()函数返回自从Flash影片开始播放以来的毫秒数。这在某些定时处理(不要求很高的准确性和精确性)中可能有用。例如,想在影片“时间到了”之后做某些循环,在这些情况下,getTimer()就是一个合适的函数。例如,可能有一个等待来自服务器的响应的影片,但是,如果30秒钟之后还没有得到响应,可能就想停止等待并提醒用户服务器没有响应。trace()trace()函数在本书中到处可见。在测试Flash应用程序显示信息时,它非常有用。isFinite()/isNaN()这些函数测试一个值是否是有限的,甚至是否是一个有效的数字。parseFloat()/parselnt()这些函数从一个字符串中解析一个数字。 十四、创建间隔函数可以用函数来做的一件非常有用的事情就是:利用setInterval()命令创建间隔函数。通过使用setInterval()函数,可以指定一个函数和一个连续调用该函数的时间间隔(以毫秒为单位)。该函数返回一个ID(标识),该ID可以被用于稍后停止该间隔。下面是setInterval()函数与一个函数一起使用时的标准语法: setInterval(function,interval,param1,paramN) setInterval()函数的第1个参数应该是一个函数的引用。这就是说,不应该包含函数调用运算符,即不能有括号。interval参数以毫秒为单位。如果给interval参数传递1000,则该函数将大约每秒钟被调用1次。但是要知道,函数被调用的间隔并不精确。Flash尽可能地按间隔来调用函数。但是,运行播放器的计算机的处理器与间隔应该多么精确之间是有冲突的。通过使用setInterval()动作,可以随意地给函数传递参数。紧接在头两个参数(必需的)之后传递给setInterval()的任何参数,都将接着传递给函数。例如,下面的例子显示了一个使用两个参数的writeMessage()函数。通过使用setInterval()可以告诉Flash,每隔1000毫秒就调用该函数,并将两个值传递给该函数: function writeMessage(sName:String,sMessage:String):Void trace(Hello,+sName+.+sMessage); var nwriteInterval:Number=setInterval(writeMessage,1000,Joey,Good morning.), Flash开发者在使用setInterval()时,常犯的一个错误是:认为会在每次调用函数时计算通过setInterval()传递给该函数的变量。例如,上面的代码可能被重新写成: function writeMessage(sName:String,sMessage:String):Void trace(Hello, +sName+.+sMessage); var sNameParam:String=Joey; var sMessageParam:String=Good morning.; var nWriteInterval:Number=setInterval(writeMessage,1000,sNameParam, SMeSsageParam); 用户可能认为:改变sNameParam或sMessageParam的值将导致在Output窗口中显示不同的值。但是,在每次调用wrlteMessage()函数时,并没有计算变量sNameParam和sMessageParam的值。相反,当调用setlrlterval()时,才计算它们一次。然后,那些值就被用于每次调用该函数。因此,尽管改变了

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论