Function类型

定义函数的三种方法:
一 函数声明语法定义函数
1         function sum1(num1,num2){
2             return num1+num2;
3         }
4         alert(sum1());//NaN(本来要返回值得操作数,却没有返回值得操作,这样就不会抛出错误,继续执行下面的代码),因为调用sum1()没有传值,所以没有返回值
5         alert(sum1(100,200));//300
6         alert(typeof sum1);//function
7         alert(sum1);//function sum1(num1,num2){return num1+num2;}

 

二 函数表达式定义函数
1         var sum2 = function(num1,num2){
2             return num1+num2;
3         };
4         alert(sum2(100,200));
5         alert(typeof sum2);//function
6         alert(sum2);//function(num1,num2){return num1+num2;}
ps:类似声明变量,语句结尾有分号;!

三 Function构造函数定义函数
1         var sum3 = new Function("num1,num2","return num1+num2");
2         alert(sum3(100,200));//300
3         alert(typeof sum3);//function
4         alert(sum3);//function anonymous(num1,num2,/**/){return num1+num2}
ps:很好的解析:函数是对象,函数名是指针

函数声明定义函数和函数表达式定义函数的区别:
1         alert(sum4(100,200));//300
2         function sum4(num1,num2){
3             return num1+num2;
4         }
ps:先调用函数再定义函数,也能正常输出!
 
1         alert(sum5(100,300));//Property 'sum5' of object [object Object] is not a function
2         var sum5 = function(num1,num2){
3             return num1+num2;
4         };
ps:函数表达式定义函数,只有当执行到函数表达式才能定义。所以先调用函数再定义函数不能正常输出!

如何理解函数没有重载!
传统意义上,只要这两个定义的签名(接受的参数的类型和数量)不同即可。
理解一:从从函数名是指针理解。
1         function sum(num1,num2){
2             return num1+num2;
3         }
4         function sum(num1,num2){
5             return num1-num2;
6         }
7         alert(sum(100,200));//-100
ps:这个例子调用的函数,实际是第二个定义的sum函数!第二次定义的sum函数覆盖了第一次定义的sum函数。
       可以理解:第一次定义的sum指针指向位置一
                     第二次定义的sum指针指向位置二,sum被重新赋值了。
 
理解二:函数的命名参数不是必须的。而且可以通过arguments对象访问函数体内的参数数组。
1         function add(num1,num2){
2             return arguments[0]+arguments[1];
3         }
4         alert(add(100,100));//200

ps:由于命名函数不是必须的,在传统意义上的函数重载在js中根本不起作用。

       但是可以利用arguments实现函数重载!     
1        function doAdd(){
2             if(arguments.length == 1){
3                 return arguments[0] + 10;
4             }else if(arguments.length ==2){
5                 return arguments[0] + arguments[1];
6             }
7         }
8         alert(doAdd(10));//20
9         alert(doAdd(10,90));//100

 

函数内部对象:arguments和this,函数内容属性:arguments.callee和caller
arguments对象用于访问函数的参数,但它有callee属性,用于消除函数的耦合。
arguments.callee是一个指针,指向该arguments所在的函数。
 1         function fun1(num){
 2             if(num<=1){
 3                 return 1;
 4             }else{
 5                 return num*arguments.callee(num-1);
 6             }
 7         }
 8         alert(fun1(5));//120
 9  
10         var fun2 = fun1;
11         fun1 = function(num){
12             return 0;
13         }
14         alert(fun2(5));//120
15         alert(fun1(5));//0

ps:即使fun1函数被重写了,fun2也能正常的递归。因为fun2指针指向原来的函数,而且arguments.callee解除了fun1的耦合。

 
this的值是函数据以执行的环境对象。通过例子理解:
1         var color = "red";
2         var o ={color:"blue"};
3         function putcolor(){
4             return this.color;
5         }
6         alert(putcolor());//red
7  
8         o.putcolor = putcolor;
9         alert(o.putcolor());//blue
ps:在全局环境调用putcolor(),当前的执行环境是全局环境,this是window对象。
       o对象定义了putcolor方法,实质o.putcolor和putcolor指向同一个函数。o.putcolor()的执行环境是o,this是o对象。
 
caller:保存着调用当前函数的函数的引用, 如果是在全局作用域中调用当前函数,它的值为null。
        function inner(){
            alert(inner.caller);
        }
        function outer(){
            inner();
        }
        inner();//null
        outer();//function outer(){inner();}

 

函数外部的属性:length和prototype,外部的方法:apply()和call()和bind()
length:代表函数里面有多少个命名参数
 1         function fun1(num1){
 2             return num1;
 3         }
 4         function fun2(num1,num2){
 5             return num1+num2;
 6         }
 7         function fun3(){
 8             return 0;
 9         }
10         alert(fun1.length);//1
11         alert(fun2.length);//2
12         alert(fun3.length);//0
 
prototype:原型模式扩展构造函数的属性。
 
apply()和call()作用一样,在特定的作 用域中调用函数,实际上等于设置函数体内this对象的值。
它们真正强大的地方是能够扩充函数 赖以运行的作用域
apply()和call()
 1         function sum(num1,num2){
 2             return num1+num2;
 3         }
 4         function callsum1(num1,num2){
 5             return sum.apply(this,arguments);
 6         }
 7         function callsum2(num1,num2){
 8             return sum.apply(this,[num1,num2]);
 9         }
10         function callsum3(num1,num2){
11             return sum(num1,num2);
12         }
13         function callsum4(num1,num2){
14             return sum.call(this,num1,num2);
15         }
16         alert(callsum1(100,200));//300
17         alert(callsum2(100,200));//300
18         alert(callsum3(100,200));//300
19         alert(callsum4(100,200));//300
ps:这个例子不能很好的突出apply和call的特点。
    但是可以很好区别apply和call第二个参数的不同:第一个参数是对象。
    但是第二个参数有区别,前者是arguments或者数组;后者为独立参数,而且不止两个参数。
 
展现扩充函数赖以运行的作用域的例子:
 1         function color(str){
 2             alert(str);
 3         }
 4         var o = new Object();
 5         o.color = function (str){
 6             alert(str+" changed");
 7         }
 8         function colorChange(str){
 9             this.color(str);
10         }
11         colorChange.apply(this,["red"]);//red
12         colorChange.apply(o,["red"]);//red changed
ps:colorChange()函数内的this值,已经被apply()的第一个参数设置了。
       因此第一个警告框输出的是window对象的color(),
       第二个警告框输出的是o对象的color()
 
1        window.color = "red";
2        var o ={color:"blue"};
3        function sayColor(){
4            alert(this.color);
5        }
6        sayColor();//red
7        sayColor.call(this);//red
8        sayColor.call(window);//red
9        sayColor.call(o);//blue
ps:call()的第一个参数设置了sayColor()的this值。
 
function.bind(object):会创建一个新函数实例,而且函数中this的值绑定到bind传入的参数,例子
1        window.color = "red";
2        var o ={color:"blue"};
3        function sayColor(){
4            alert(this.color);
5        }
6        var anotersayColor = sayColor.bind(o);
7        anotersayColor();//blue
ps:可见bind()的用途
 
 
posted @ 2014-04-04 17:23  chenjjjjj  阅读(333)  评论(0编辑  收藏  举报