JavaScript里函数的定义方式与函数的调用方式
函数的定义
函数的定义方式有三种:
- 定义命名函数
- 定义匿名函数
- 使用function类匿名函数
作为弱类型语言,JavaScript既不需要函数的返回值,也不需要声明函数的参数类型;而函数的最大作用就是提供代码的复用,将需要复用带代码定义成函数
1:定义命名函数
<script type="text/javascript">
hello('World!');
// 定义函数hello,该函数需要一个参数
function hello(name)
{
alert(name + ",你好");
}
</script>
function 后面直接定义函数名(hello),括号里面是参数,且不需要函数类型,也没有返回值,但是可以使用:
return ;
return value;
return 和高级语言的return一样,用结束函数,而return value;则在结束函数的同时返回某个值,return后面可以接任何值,如果你高兴,return后面还可以接一个函数(虽然函数不定义返回值,但是可以返回某个值)
2:匿名函数
<script type="text/javascript">
var f = function(name)
{
document.writeln('匿名函数<br />');
document.writeln('你好' + name);
};
f('aile');
</script>
在这里我们可以看到,函数没有函数名,而是通过 “=” 赋值给 f ,这里也可以不给 f ,但是这样,这个函数就白定义了,因为你没法调用,赋值给f后就可以将f当做函数名使用,和命名函数的使用方式一样
3:Function类匿名函数
在JavaScript里面,有Function这么一个类,Function类的构造器的参数个数可以不受限制
<script type="text/javascript">
// 定义匿名函数,并将函数赋给变量f
var f = new Function('name' ,
"document.writeln('Function定义的函数<br />');"
+ "document.writeln('你好' + name);");
// 通过变量调用匿名函数
f('aile');
</script>
如以上代码,最后一个字符串参数是函数的执行体,且个语言用“;”隔开。而前面的字符串就是参数,和匿名函数一样,赋值给f,要不然这种方式的函数就以为无法调用而白定义了
局部函数,即函数里面的函数
<script type="text/javascript">
function a()
{
alert("aile");
function b()
{
alert("Hello World!");
}
}
b();
</script>
执行结果:
函数b();报错说未定义,所以,局部函数(函数内部的函数)只能在所属的函数内部使用,而不能离开函数体
函数的调用
函数的调用方式也有三种:
- 直接调用函数
- 以call()方法调用函数
- 以apply()方法调用函数
1:直接调用
<script type="text/javascript">
function a ()
{
//函数体
}
a();
</script>
最普通最常见,直接调用,不搞那么花里胡哨
2:利用call()
由于直接调用函数太简单粗暴,所以不够灵活,因为当有时候需要调用函数时需要动态地传入一个函数的引用,此时就可以用call()了
定义方式:FunctionName.call(调用者,参数1,参数2 . . .)
<script type="text/javascript">
function f(name,fn)
{
fn.call(this,name);
}
f("aile",function(name){
alert(name);
})
</script>
上面将输出"aile",这个函数定义时时,我们只知道要对这个name进行操作,但是具体未确定,所以这是就需要一个动态函数,因为fn未定义时,就无法调用,但是我们又需要一个队name操作的函数,所以这是就使用call()来进行动态调用,这样在具体操作时传入具体函数,比如当需要在警告框输入name,就将fn定义为alert(),当需要将name在body体输出时,则将fn定义为document.writeln();
关于调用者:上述代码由于是在f里面直接调用输出,所以可以为this也可以为null;这里的name是传进来的没如果不是传进来的而是使用的该函数体内的如:this.name,这是调用者的作用就很大,因为函数具有独立性(后面讲),不同调用者,结果将会哦不一样
3:利用apply()
这个其实和call()基本一样,唯一的差别就是传参的差别
使用方式:FunctionName.apply(调用者,[参数1,参数2 …]);
<script type="text/javascript">
// 定义一个函数
var myfun = function(a , b)
{
alert("a的值是:" + a
+ "\nb的值是:" + b);
}
// 以call()方法动态地调用函数
myfun.call(window , 12 , 23);
// 以apply()方法动态地调用函数
myfun.apply(window , [12 , 23]); // ①
var example = function(num1 , num2)
{
// 直接用arguments代表调用example函数时传入的所有参数
myfun.apply(this, arguments);
}
example(20 , 40);
// 为apply()动态调用传入数组
myfun.apply(window , [12 , 23]);
</script>
区别即时,即时参数有千千万个,但是在apply()里面,你只要写一个arguments就够了,但是call()就一定要写完,所以当你不知道具体要传多少参数时,可以使用apply(),当知道时,apply()与call()就随便挑了
函数的独立性
函数时独立的,他永远不属于其他类,或者对象
<script type="text/javascript">
function Person(name)
{
this.name = name;
// 定义一个info方法
this.info = function()
{
alert("我的name是:" + this.name);
}
}
var p = new Person("aile");
// 调用p对象的info方法
p.info();
var name = "测试名称";
// 以window对象作为调用者来调用p对象的info方法
p.info.call(window);
</script>
执行结果:
第一个输出,输出的是 p传入的“aile”,因为函数具有独立性,所以函数体及this关键字是属于p,所以name是"aile"
但是第二个利用call()的,调用者确实,所以函数体及关键字,都是来自于window,由于上面定义了 var name = “测试名称”
是全局变量,即是对象window的(JavaScript规定,全局变量都是window的),所以输出“测试名称”