JavaScript 4.1 函数高级-理解函数
JavaScript中变量可以分为两类:基本类型和引用类型(有时也称对象)。其中数值、字符串、布尔值、null和undefined属于基本类型;对象、数组和函数属于引用类型(对象)。
基本类型在内存中具有固定的内存大小。例如:数值型在内存中占有八个字节,布尔值只占有一个字节。对于引用型数据,他们可以具有任意长度,因此他们的内存大小是不定的,因此变量中存储的实际上是对此数据的引用,通常是内存地址或者指针,通过它们我们可以找到这个数据。
在ECMAScript中,函数是对象,每个具体函数都是Function对象的实例。函数可以作为变量来使用,变量名作为指向函数的指针来使用。
1.函数定义:
函数声明法:
function functionname(){···} //没分号
函数表达式:
var x = function(){···}; //有分号
注1:函数可以没有函数名,如function(){}; 被称为匿名函数。可以运行,在onclick中常用。但是没有办法被再次引用,没有名字嘛,就没有指向这个函数的指针。
注2:在函数表达式中,将函数赋给变量x,x保存的是函数指针。与函数声明中的functionname是一样的。
注3:在JavaScript中,函数定义里可以嵌套函数定义。而这在C语言中是不允许的。
例如1:
function Func1(){
····
function Func2(){
···
}
}
//
当调用函数:
Func1();
的时候,
Func2()
是不执行的。因为在
Func1()
里,只是定义了
Func2
。
例如2:
function Func1(){
var num=0;
return function(){
return num;
};
}
alert(Func1()); //结果显示:function(){return num;}
alert(Func1()()); //结果显示:0
注
4
:函数声明与函数表达式的区别只有一点:函数声明可以函数声明提升,意思就是在执行代码前先读取函数声明。例如:
sayHi(); //没有问题
function sayHi(){···}
sayHi(); //错误,函数还不存在
var sayHi = function(){···};
2.函数名的使用:
function sum(num1,num2){
return num1+num2;
}
var x1=sum;
sum(1,2); //3
x1(1,2); //3
var display = function(){alert("Hello World!")};
x2=display;
display(); //Hello World!
x2(); //Hello World!
var object = new Object();
object.m = sum; //给对象object定义了m()方法。
object.m(1,2); //3
注:函数名作为指针可以任意赋值,函数名
()
表示调用指针指向的函数。
3.函数的使用:
①作为值
function aaa(){
return 10;
}
var x = aaa(); //x = 函数的返回值10
function aaa(){
return aaa;
}
var x = aaa(); //x = 函数的返回值aaa,即函数指针。
②作为函数的返回值
function Func1(){
var num=0;
return function(){
return num;
};
}
alert(Func1()); //结果显示:function(){return num;}
alert(Func1()()); //结果显示:0
③作为构造函数
function person(name,age) {
this.name=name;
this.age=age;
}
var myFather = new person("John",50); //结果:创建myFather.name="John",myFather.age=50
alert(myFather.age); //50
function test(){
this.x = 1;
}
var o = new test(); //结果:创建o.x=1
alert(o.x); // 1
4.指向函数的指针arguments.callee
在保存函数参数的对象arguments中有一个名叫callee的属性,该属性是一个指针,指向函数。等同于函数名。
//在递归函数中,函数通过函数名调用自身:
function multiple(num){
if(num<=1){
return 1;
}else{
return num*multiple(num-1);
}
}
//因为在函数中用来multiple这个函数名,当:
var a = multiple;
multiple = null;
a(4); //出错。
//为了消除这种紧密耦合的现象,可以:
function multiple(num){
if(num<=1){
return 1;
}else{
return num*arguments.callee(num-1);
}
}
//缺点:在严格模式下,不能使用arguments.callee,解决方法:
var multiple = (function f(num){
if(num<=1){
return 1;
}else{
return num*f(num-1);
}
});
//解释:这是模仿块级作用域。
5.模仿块级作用域
JavaScript 没有块级作用域的概念,在 if for while 等中定义的变量是全局变量。比如我们写了一点 JavaScript 模块代码,需要放在不同 JavaScript 程序中,我们需要几个局部变量 ( 比如中间变量 ) ,我们需要模仿块级作用域。解决方法:将代码放在一个函数中。
方法1:
function mymodule(){
···一段代码
}
mymodule(); //不要忘了调用函数
方法2:推荐
( function(){
···一段代码
} ) ()
理解:
用函数表达式时,var x=function(){}; x(); 将function(){···}看成x,()防止JavaScript将function关键字作为函数声明的开始。
方法3:
( function(){
···一段代码
} () )
理解:
()表示立即执行,()防止JavaScript将function关键字作为函数声明的开始。