函数是对象,函数名是指针
function sum(num1,num2){ return num1 + num2; } alert(sum(10,20)); //30 var anotherSum = sum; //相当于把another指向sum所指向的空间 alert(anotherSum(10,10)); //20 sum = null; alert(anotherSum(10,15)); //25
函数声明与函数表达式的区别
1.函数声明
alert(sum(10,20)); //30 function sum(num1,num2){ return num1+num2; }
2.函数表达式
alert(sum(10,20));//TypeError: sum is not a function var sum =function(num1,num2){ return num1+num2; } //在执行到函数所在的语句之前,变量sum中不会保存有对函数的引用
ps:也可以同时使用函数声明和函数表达式,例如var sum=function sum(){},不过在Safari中会导致错误。
作为值的函数
function callSomeFunction(someFunction,someArgument){ return someFunction(someArgument); } function add10(num){ return num+10; } function getGreeting(name){ return "hello, "+name; } var result = callSomeFunction(add10,10); //20 var result2 = callSomeFunction(getGreeting,"Yoyo");//hello, Yoyo alert(result+" "+result2);
ps:要访问函数的指针而不执行函数的话,必须去掉函数名后的那对圆括号。传递给callSomeFunction()的是add10和getGreeting,而不是执行它们之后的结果。
例子:有个对象数组,要按照对象某个属性,对数组进行排序。
function createComparisonFunction(propertyName){ return function(o1,o2){ var value1 = o1[propertyName]; var value2 = o2[propertyName]; if(value1<value2){ return -1; }else if(value1>value2){ return 1; }else{ return 0; } } } var data = [{name:"Yoyo",age:24},{name:"Peter",age:23},{name:"Adam",age:29}]; data.sort(createComparisonFunction("name")); var i; for(i=0;i<data.length;i++){ alert(data[i].name+" "); //Adam,Peter,Yoyo } data.sort(createComparisonFunction("age")); for(i=0;i<data.length;i++){ alert(data[i].name+" "); //Peter,Yoyo,Adam }
函数的内部属性:arguments和this
例如:对斐波纳西数列的求解,在不使用arguments.callee时,重写factorial函数的函数体,值会改变
function factorial(num){ if(num<=1){ return 1; }else{ return num*factorial(num-1); } } alert(factorial(4)); //24 var trueFactorial = factorial; factorial = function(){ return 0; } alert(trueFactorial(4)); //0
当使用arguments.callee时,factorial函数体发生改变,对值没有影响
function factorial(num){ if(num<=1){ return 1; }else{ return num * arguments.callee(num-1); } } alert(factorial(4)); //24 var trueFactorial = factorial; factorial = function(){ return 0; } alert(trueFactorial(4)); //24
this的使用
window.color = "red"; var o = {color:"blue"}; function sayColor(){ alert(this.color); } sayColor(); //red ;在全局作用域中调用sayColor()函数时,this引用的是全局对象window o.sayColor = sayColor; o.sayColor(); //blue ; 当把这个函数赋给对象o并调用o.sayColor()时,this引用的对象是o //全局的sayColor()函数 与 o.sayColor()指向的是同一个函数。
函数的属性和方法 :
1.每个函数都包含两个属性:length和prototype
1)length属性:表示希望接受到的命名参数的个数
function sayName(name){ alert(name); }; function sum(num1,num2){ alert(num1 + num2); } function sayHi(){ alert("hi"); } alert(sayName.length); //1 alert(sum.length);//2 alert(sayHi.length);//0
2)prototype属性
2.每个函数都包含两个非继承而来的方法:apply()和call()
1)apply()方法接受两个参数:一个是在其中运行函数的作用域,另一个参数是数组(可以是Array的实例,也可以是arguments对象)
2)call()方法,第一个参数是this值没有变化,变化的是其余参数都直接传递给函数(传递给函数的参数必须是逐个列举出来)
function sum(num1,num2){ return num1+num2; } //第二个参数使用arguments function callSum1(num1,num2){ return sum.apply(this,arguments); } //第二个参数使用Array实例 function callSum2(num1,num2){ return sum.apply(this,[num1,num2]); } //使用call()方法 function callSum3(num1,num2){ return sum.call(this,num1,num2); } alert(callSum1(10,20)); //30 alert(callSum2(10,10)); //20 alert(callSum3(10,21)); //31
- 传递参数并非apply()和call()真正的用武之地;它们真正强大的地方是能够扩充函数赖以运行的作用域。
window.color = "red"; var o = {color:"blue"}; function sayColor(){ alert(this.color); } sayColor(); //red sayColor.call(this); //red sayColor.call(window); //red sayColor.call(o); //blue
3.ECMAScript 5还定义了一个方法:bind().
window.color = "red"; var o = {color:"blue"}; function sayColor(){ alert(this.color); } var objectSayColor = sayColor.bind(o); objectSayColor(); //blue
每个函数继承的toLocaleString()和toString()方法都始终返回函数的代码
function show(){ var a = "hello"; var say = function(){ alert("Byebye"); } return 0; } alert(show.toLocaleString()); //输出的结果是show()的代码