javascript 基础 Function类型
函数--可以说是ECMAScript中最有意思的部分了。
函数实际上是对象,每个函数都是Function类型的实例。函数名实际上是一个指向函数对象的指针。
除了我们常见的两种函数声明方式,函数声明与函数表达式,还有一种使用Function构造函数创建,
例:
//Function构造函数方式 var sum = new Function("num1","num2","return num1+num2"); alert(sum(1,3));
解释:函数是对象,函数名是指针。
function sum(num1.num2){ return num1 + num2; } alert(sum(10,20)); // 30 var anotherSum = sum; // 指向同一函数 alert(anotherSum(10,20)); // 30 sum = null; // sum引用指针为空,断绝于函数的关系,此时anotherSum指向的仍为那个函数 alert(anotherSum(10,20)); // 30 anotherSum指针指向的是真实对象,跟sum无关
注:使用不带圆括号的函数名访问的函数指针,而非调用函数;
1-2 函数重载
从语言角度讲,javascript不支持函数重载,不能够define相同的函数名然后编译器识别不同的参数执行不同的函数体。
但javascript可以通过自身属性模拟函数重载。
最基本函数重载,例:
function addSomeNumber(num1,num2,num3){ // 根据函数参数个数判断,实现函数重载 if(arguments.length==1){ return arguments[0]; } if(arguments.length==2){ return arguments[0]+arguments[1]; } if(arguments.length==3){ return arguments[0]+arguments[1]+arguments[2]; } }
function myInfo(name, password, email){ //根据函数参数类型判断,实现函数重载 if(typeof(email) != "undefined"){ alert("填写信息正确"); }else if(typeof(password) != "undefined"){ alert("email地址没有填写"); }else { alert("密码不能为空"); } }
这种方法实现要领:将必须的参数放前面,将可以省略的参数放后面,未传入的参数类型是undefined.
1-3 作为值的函数
javascript中函数名就是变量,不仅可以把函数作为参数传递,也可将一函数作为另一个函数的结果返回,即return一个函数.
函数作为参数传递,例:
1 function callSomeFunction(someFunction, someArgument){ 2 //someFunction参数传递函数,注意不要加(),这里传递的是函数引用 3 return someFunction(someArgument); 4 } 5 function add10(num){ 6 return num+10; 7 } 8 9 var result1 = callSomeFunction(add10, 20); 10 alert(result1); // 30 11 12 function getGreeting(name){ 13 return "hello "+name; 14 } 15 16 var result2 = callSomeFunction(getGreeting,"han"); 17 alert(result2);
在一函数中返回函数,例:
1 /** 函数作为另一函数返回值 **/ 2 function createComparisonFunction(propertyName){ 3 // 返回函数 4 return function(obj1, obj2) { 5 var value1 = obj1[propertyName]; 6 var value2 = obj2[propertyName]; 7 8 if(value1 < value2){ 9 return -1; 10 }else if(value1 > value2){ 11 return 1 12 }else{ 13 return 0; 14 } 15 } 16 } 17 var data = [{name: "han",age: 22},{name: "Nicholas", age: 28}]; 18 data.sort(createComparisonFunction("name")); 19 alert(data[0].name); 20 data.sort(createComparisonFunction("age")); 21 alert(data[0].age);
1-4 函数内部属性
两个特殊属性arguments和this,相信写过javascript代码的对这两个都不陌生。
arguments是一个类数组对象,包含传入的所有参数,arguments对象还有一个callee的属性,该属性是个指针,指向拥有这个arguments对象的函数,即(原函数).
例:
function factorial(num){ if(num<=1){ return 1; }else{ return num*arguments.callee(num-1); } } alert(factorial(5));
对象this,与java中的this类似,this引用的是函数据以执行操作的对象。
1 window.color = "red"; 2 var o ={ color:"blue"}; 3 4 5 function sayColor(){ 6 alert(this.color); 7 } 8 9 sayColor(); // "red" 10 o.sayColor = sayColor; 11 o.sayColor(); // "blue"
请牢记:函数的名字仅仅是一个包含指针的变量而已,即使在不同的环境中执行,全局的sayColor()与o.sayColor()调用的仍是同一个函数。
1-5 函数属性和方法
1,每个函数都含有两个属性:length和prototype。
length属性表示函数希望接收的参数
2,prototype是最值得深究的属性,prototype是保存它们所有实例方法的真正所在。诸如toString()和valueOf()都在prototype名下。
3,非继承的方法apply()和call(),apply和call第一个参数都是传入作用域,第二个参数apply需要传入参数数组,call是一个个参数传入
他们的使用实例,
1 function sum(num1,num2){ 2 return num1+num2; 3 } 4 // apply方法,参数按数组传入 5 function callSum1(num1, num2){ 6 return sum.apply(this, arguments); 7 } 8 function callSum2(num1, num2){ 9 return sum.apply(this,[num1,num2]); 10 } 11 alert(callSum1(10,10)); //20 12 alert(callSum2(10,10)); //20 13 14 //call方法,参数一个个传入 15 function callSum3(num1, num2){ 16 return sum.call(this,num1,num2); 17 } 18 alert(callSum3(10,10)); //20
apply和call的最大作用还在于扩充函数赖以运行的作用域,对象不需要与方法有任何耦合关系。例:
1 //最大的作用,扩充函数赖以运行的作用域 2 window.color = "red"; 3 var o = {color: "blue"}; 4 5 function sayColor(){ 6 alert(this.color); 7 } 8 9 sayColor(); //red 10 sayColor.call(this); // red 11 sayColor.call(window); // red 12 sayColor.call(o); // blue 13 //最后这个,不需要在对象o里传入sayColor方法了,可以直接通过window对象中的sayColor方法调用了
4,继承的toLocaleString()和toString()方法始终返回函数的代码
2 高级函数重载
由于现在能力有限,高级函数重载后续再写