函数本身也是一个对象,因此函数本身也具有属性与方法。每一个函数实质上都是 Function 的实例,因此每一个函数内部可以使用 Function 类定义的属性与方法,函数名实质上就是指向函数对象的指针。
function Demo(){
age:111
}
alert(Demo.constructor) // function Function() { [native code] }
alert(Demo.__proto__ == Function.prototype) // true
上面代码说明:任何一个函数,都是 Function 的对象,所以每一个函数不单单是函数,同时也是对象。
定义
函数常用的定义方式有两种:
function f1(arg1,arg2){
return arg1+arg2+",f1";
}
var f2 = function(arg1,arg2){
return arg1+arg2+",f2";
}
alert(f1(1,3)) //4,f1
alert(f2(3,4)) //7,f2
- 其实函数还有第三种定义方式:通过 Function 类的构造函数,但该种方式会解析两次,影响性能,所以不推荐。
函数名
函数名也是一个普通的变量,所以它可以用来做为另一个函数的返回值,也可以用来做为参数传递到另一个函数中。普通变量能有的功能,它也都具有。注意:一旦函数名后跟 (),则表示需要执行该函数。
function f1(f2,num){
return f2(num)+num;
}
var f2 = function(num){
return num+1;
}
alert(f1(f2,4)) // 将函数 f2 当作参数传入到另一个函数 f1中。
alert(f1(f2(2),4)) // 本句话会报错
- 最后一个语句会报错,因为 f2 后跟有 (),表示执行函数 f2,而 f2 执行的结果是数字 3,系统会将数字 3 当作实参传递到 f1 中,因此 f1 得到的参数就是 3 与 4,即 f2 代表的实参是 3,不是一个函数,所以没办法在 f1 中调用 f2(num)。
arguments 属性
arguments 是每一个函数都具有的属性,因此可以在任意的函数内部使用该属性,也可以在函数外部通过函数名引用该属性。它有如下两个功能:
存储实参
在JS 中,函数不介意形参与实参的个数是否一致,也不介意传递进来的参数是什么类型的。在函数中,可以通过 arguments 数组获取传递进来的实参。如果 arguments 取的下标没有传递对应的实参,则该值为 undefined。
test(1);
test("222",{});
function test(){
alert(arguments[0]+"---"+arguments[1]);
}
通过 arguments 获取实际传入的参数。传递一个参数时,arguments[1] 的值便是 undefined。
callee 方法
表示当前方法。arguments 并不单单是一个数组,它也是一个对象,里面有 callee 方法 。
它是 arguments 这个对象的方法,并不是函数的方法,因此调用时必须通过 arguments ,而不是直接使用函数名调用。注意与下面的 call 与 apply 的调用者区别。
下面的代码是计算阶乘的代码,但在递归时没有直接使用 f1 函数名,而是使用了 arguments.callee 方法,它就表示了 f1 函数。这可以保证在修改函数名时,不需要再修改函数内部的各个调用地方。
var f1 = function (num) {
if(num <= 1)
return 1;
return num * arguments.callee(num - 1);
}
alert(f1(5)); // 返回 120
this 属性
函数的属性,表示调用这个函数的对象。与 java 中的 this 一样。
length 属性
表示函数在定义时,形参的个数,跟传入多少个实参没有任何关系。
var f = function(){
alert(f.length) // 输出的是 0,因为定义时没有定义形参
}
f(1,2)
apply() 与 call()
它是每一个函数的方法,因此可以通过函数名直接调用。其作用是 在特定的作用域中调用函数,也就是设置函数体内 this 的值,也即是说 在指定的对象中运行指定的函数。
var name = "window's name"
var o = {
name:"o's name"
}
var f = function(age){
alert(this.name+","+age)
}
f(30) //window's name,30
f.call(o,20) // o's name,20
f.apply(o,[10]) //o's name,10
-
第一次调用 f() 时,this 指代的是 window 对象,所以 this.name 就是外层的 name 属性值
-
第二,三次调用时,指定了 f 函数的作用域是 o 对象,所以 this 指代的就是 o 对象。
-
call 与 apply 的区别在于:apply 第二个参数必须是一个数组,而 call 可以将数组的值拆开传递。
call 与 apply 方法也可用于某个对象中的方法上。
var o = {
age:19
}
o.f = function(){
alert(this.age)
}
var o2 = {
age:200
}
o.f(); // 输出 19
o.f.call(o2) // 输出 200
网友评论