欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javascript函数

程序员文章站 2024-03-17 18:02:34
...
函数是指定义一次却可以调用多次或是运行多次的javascript代码段。要学好javascript,弄清楚函数是必要的。

学习函数必须要弄清楚以下几点:
1. 声明方法
2. 作用域
3. 函数参数
4. 函数调用

一. 声明

一般函数有三种声明方法,如下所示:
function f1(x,y)
{
return x*y;
}
var f2 = function(x,y)
{
return x*y;
}
var f3 = new Function("x", "y", "return x*y; ");

前面两种应该是经常见到的,最后一种声明方式特殊一点,他接受n个参数(n>1),前n-1个参数是新函数的参数,最后一个参数是函数体。这种声明方式可以允许用户根据字符串动态创建一个函数,但每new Function一次就会动态编译并生成一个新的对象,如果调用了十次new Function,就生成了十个新的对象,如果放在经常调用的地方或是循环体内效率就低了。

二.函数的作用域

对于函数来说,他的作用域是在定义的时候就决定的,而不是在他调用的时候决定。但是用new Function声明的函数,他的作用域是全局,相当于是在全局定义的函数。关于具体的作用域知识,可以参考我之前写的文章:Javascript作用域浅析 。

三,函数的参数。

虽然函数声明时定义了参数列表,但这个参数列表其实只是提供了对应参数的一个快速引用而已。函数是可以用任意多的参数调用的。下面的函数f1跟注释掉的函数f1定义是一样的函数:
function f1(x,y)
{
return x*y;
}
/*
function f1()
{
x = arguments[0];
y = arguments[1];
return x*y;
}

在上面,我们看到了一个特殊的对象: arguments,注意,arguments并不是数组,它只是一个对象。arguments里面存贮了实际的调用参数,它和参数列表里面的参数是维护同一份数据的。下面的例子有助于理解。
function f1(x,y)
{
arguments[0] = 1;
return x*y;
}
alert(f1(3,5)); //will display 5

上面的例子中,我们修改了arguments[0],同时参数列表里面的x的值也改变了。arguments还有两个属性,一个是length,指出参数的个数,还有一个属性callee,指向函数。下面我们用callee来计算阶乘:
var result = (function(x)
{
if(x <=1) return 1;
return x* arguments.callee(x-1);
})(3);
alert(result);//will display 6

四.函数的调用

函数可以作为数据进行传递,但函数的作用域是在定义时候决定的,那么函数由谁调用有没有什么不同呢?答案是有的,差别就在于 this关键字。每个函数内部,都可以用this引用调用它的对象,读取或是修改对象的属性。所有没有声明调用对象的函数,默认都是由window调用,我们看看下面的例子:
var name= "window";
var person = {
name : "person",
f1 : function()
{
return this.name;
}
}
var f2 = person.f1;
alert(f2()); //will display window
alert(window.f2()); //will display window
alert(person.f1()); //will display person
alert( person.f1.call(window) ); //will display window
alert( person.f1.call(person) ); //will display person
alert( person.f1.apply(window) ); //will display window

在上面,我们看到了this关键字指向的对象就是调用他的对象。其中,我们还看到了另外两种调用的方式:call, apply。这是函数的两个属性,可以用来调用函数,第一个参数都是指调用对象,而对于调用函数的参数,call是一个一个罗列,如 .call(obj, x, y),而apply是使用数组,如 .apply(obj, [x, y]) 。

到这里我们可以知道:

函数的作用域是定义时候确定的,是调用无关的。
函数是实现特定功能的代码段,由谁调用是定义无关的。比如A对象可以调用B对象内定义的方法。例如:我们可以用随便一个对象对用Array定义的方法。
var p = {
length : 0
}
Array.prototype.push.apply( p, [3, 4, 5] );
alert(p.length); // will dispay 3
alert(p[1]); //will dispay 4

最后,我们再来看看关于setTimeout()的调用。setTimeout函数是系统在window对象下直接初值化的一个函数,他并没有 call属性,所以只能用setTimeout()或是window. setTimeout()调用。它接受两个参数,第一个是运行的代码,它可以是字符串,也可以是一个函数。第二个参数是间隔时间,指多少时间后运行代码,以毫秒为单位。
如果第一个参数是字符串,javascript就会默认是javascriipt代码段,到时间后会在全局作用域下运行改 javascript代码。就是说里面的作用域是全局,调用对象是 window。
如果第一个参数是函数,那么函数的作用域是已经定了的,不过调用对象是window。
我们看一下下面的例子。
var name="window";
var p = {
name: "obj",
fun : function(){
var name="local";
alert(this.name); //if p call it ,will display obj
setTimeout("alert(name + ' and ' + this.name);", 1000); //all will display "window and windows"

setTimeout(function(){
alert(name); //will display local
alert(this.name); //will display window
}, 2000);
}
}
p.fun();

setInterval与setTimeout的区别在于setTimeout是只执行一次,而setInterval是间隔多少时间就执行一次,单是函数调用以及作用域的问题他们是一致的。