Js_Function

1.函数的定义

函数就是一个特殊的对象,是一个Function类的实例,其实在内存中存储的操作是通过一个键值对来存储的
函数的名称仅仅只是一个键,值指向的是内存中的一个对象,这个对象就是function对象

             function fn1(){
                 alert("fn1");
             }      

由于函数是一个对象,所以可以通过如下方式进行定义:
以下是通过函数的拷贝来完成赋值的,两个引用并没有指向同一个对象

         var fn2 = fn1; //内存中是将fn1的内容拷贝到fn2
         fn2(); //--> fun1
         fn1 = function(){ alert("fnn1");}

函数虽然是一个对象,但是和对象有一些区别,对象是通过引用的指定完成对象的赋值的,而函数却是通过对象的拷贝来完成的
所以fn1虽然变了,并不会影响fn2

         fn2(); // --> fn1
         fn1(); // --> fnn1

对象是通过引用的指定完成对象的赋值的,此时修改o1或者o2会将两个值改变

         var o1 = new Object();
         var o2 = o1;
         o2.name = "Leon";
         alert(o1.name); //-->Leon

2.函数的重载

函数就是一个对象,不存在重载,只存在覆盖,后边定义的覆盖前面定义的

         function sum(sum1,sum2){
             return num1+num2;
         }
         //相当于
          -->  
               var sum = function(sum1,sum2){
                     return num1+num2;
               }

此时sum所指向的内存空间已经从有两个参数的函数变化成只有num1的函数中在调用的时候就只会调用只用num1的函数
特别指出:函数的参数和调用没有关系,如果函数只有一个参数但传入两个参数,仅仅只匹配一个,所以js中不存在重载

         function sum(num1){
             return num1+100;
         }
         //相当于
         -->  
               var sum = function(sum1,sum2){
                     return num1+num2;
               }

         alert(sum(19));//-->119

         alert(sum(19,20));// -->119

函数有如下创建方式

         var fn = new function (arg1,arg2,...,argn,function body);
         var fn = new function ("num1","num2","alert(num1+num2)");

3.函数的值传递

由于函数是一个对象,我们就可以把fun当作一个参数传递

             function callFun(fun,arg){
                 return fun(arg);
             }

             function say(str){
                 alert("hello"+str);
             }
               -->相当于
                  var say = xxx  //这是一个对象

             callFun(say,"Leon"); //将say传入fun fun相当于指向say的内存空间

             function sum(num){
                 return num+100;
             }

             alert(callFun(sum,20));  //如此就是灵活性的改变
             function fn1(arg){
                 /**
                     此时返回的是一个函数对象
                 **/
                 var re1 = function(num){
                     return arg+num;
                 }
                 return rel;
             }

             //
             var f = fn1(20);//f是一个函数对象  所带来的好处就是 arg参数的作用域被放大 可以在任何时候再次调用  带来更多的灵活性

             alert(f(11));//如此可以完成对这个函数的调用

4.函数的argument

在函数对象中有一个属性arguments,通过这个属相可以获得相应的参数值,这个属性可以获取相应的参数值。
这个属性是一个数组,其实就是传递进来的参数

             function say(num){

                 alert(arguments.length); // -->3
                 alert(num);// --> 1
                 forvar i=0;i<arguments.length;i++){
                     alert(arguments[i]); // 1 2 3
                 }
             }
             say(1,2,3);

在agruments这个对象中有一个callee的方法,arguments.callee(arg)可以反向调用

             function factorial(num){
                 if(num<=1) return 1;
                 //此时是耦合在一起的
                 else return num*factorial(num-1);
             }


             /**
                 以上是一个求阶乘的函数,以上递归函数用的函数名称和原有的函数名称耦合在一起,如果将来这个函数名称更改之后,
                 递归调用就会失效
             **/
             var cf = factorial;
             //此时不会报错
             alert(cf(5));//120
             //此时由于cf这个函数依然使用factorial这个名称来调用,但是factorial已经指向null了,所以就会报错
             //如上情况就需要arguments.callee方法来调用
             factorial = null;
             alert(cf(5));//报错


             function factorial_1(num){
                 if(num<=1) return 1;
                 //以下实现函数名的解耦和,在js中都是通常使用这种方式做递归
                 else return num*arguments.callee(num-1);
             }

             var cf = factorial_1;
             factorial_1 = null;
             alert(cf(5));

5.函数的this

当需要创建一个类的时候,设置类的属性和方法需要通过this关键字来引用
但是特别注意:this关键字在调用时会根据不同的调用对象而变得不同

         var color ="red";
         function showColor(){
             alert(this.color);
         }

创建一个类,有一个color的属性和一个show的方法

         function Circle(color){
             this.color = color;
             this.show = showColor;
         }

         var c = new Circle("yellow");
         //使用c来调用show方法,等于调用了showColor()方法
         //现在的this是c
         c.show();// --> yellow


         //此时调用的对象是window
         //this是window,就会找window的color
         showColor();

6.函数的属性

函数有两个非常有用的属性:length 和 prototype
length指的是该函数所期望传递进来的参数个数

             function fn1(){}

             function fn2(num1,num2){}

             function fn3(num3){}


             alert(fn1.length);// --> 0
             alert(fn2.length);// --> 2
             alert(fn3.length);// --> 1

7.函数的方法

函数有两个非常有用的方法:call apply
这两个方法是可以通过函数名称来调用的函数
对于apply而言:
有两个参数,第一个是调用的上下文,第二个是参数数组,可以直接把arguments传递进去
对于call而言
第一个参数是上下问对象,后面的参数是不同函数参数

             function sum(num1,num2){
                 return num1+num2;
             }

             function callSum1(num1,num2){
                 //使用sum这个函数来完成一次调用,调用的参数就是callSum1这个函数的参数

                 return sum.apply(this,arguments);
             }

             function callSum2(num1,num2){
                 //关键是第二个参数是数组

                 return sum.apply(this,[num1,num2]);
             }

             alert(callSum1(12,22));// -->34
             alert(callSum1(22,32));// -->54



             function callSum3(num1,num2){
                 //call是通过参数列表来完成传递,其他没有任何区别

                 return sum.call(this,num1,num2);
             }

Ex

         var color ="red";
         function showColor(){
             alert(this.color);
         }

         function Circle(color){
             this.color = color;
         }

         var c = new Circle("yellow");           

         showColor.call(this);  //使用上下文调用,结果是 red   
         showColor.call(c); //使用上下文调用,结果是 yellow    

通过以上发现,使用call和apply之后,对象可以不需要定义方法
就是call和apply的一种运用


版权声明:本文为qq_31179919原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。