js函数知识

1、函数基本知识

通过函数可以封装任意条语句,在任何地方调用,js中用function关键字来声明,

        //基本格式,函数名,传递参数,代码块
        function functionName(arg0,arg1,arg2,……,argN){
             statements
        }
        
        //实例
        function sayHi(name,message){
              console.log("hello "+name+","+message)
        }
        sayHi("double","how are you")    //普通的函数名调用函数

        function sum(numb1,numb2){
             return numb1+numb2;
             console.log("find me ?")    //因为之前有return,所以不会再执行
        }
        var result=sum(1,2);             //声明变量的做法来调用函数


        function summ(numb1,numb2){
              return;                    //return可以不带任何返回值,这时候会返回undefined
              console.log("hello")
        }

        function diff(numb1,numb2){      //一个简单的比较函数
             if(numb1<numb2){
                  return numb2-numb1;
             }
             else{
                  return numb1-numb2;
             }
        }

1.1理解参数

js中的参数在其内部使用一个数组表示,所以无论参数的数据类型,个数都没关系,而且参数也不一定会用上的。

函数体内可以通过arguments对象访问到参数的数组,从而获得每一个参数。arguments对象和数组相似,可以中括号表示,有length;

参数名不是必须的,为了方便而已,也可以通过arguments[0]访问到

        function change(){
            console.log(arguments.length)
        }
        var zero=change()         //0      可以通过length来展现
        var one=change("one")     //1
        var two=change("two",2)   //2
        
        //没有参数名
        function doAdd(){
            if(arguments.length==1){
                console.log(arguments[0]+10);
            }else if(arguments.length==2){
                console.log(arguments[0]+arguments[1])
            }
        }
        doAdd(1)      //11
        doAdd(1,2)    //3

        //有参数名
        function anotherAdd(num1,num2){
            if(arguments.length==1){
                 console.log(num1+10);
            }else if(arguments.length==2){
                 console.log(num1+num2)
            }
        }
        anotherAdd(1)    //11
        anotherAdd(1,2)  //3

        function again(num1,num2){
            arguments[1]=10;
        //这里num2的值也就变成10,arguments的值与对应命名参数的值保持同步,内存空间还是独立的;没有传递值得命名参数为undefined          
            console.log(arguments[0]+num2)
        }

1.2没有重载

所谓的没有重载就是说,不可以为函数两个定义,因为js的参数是数组,没有签名,做不到真正的重载。两个相同的函数则以后一个为准。

Function类型

也是引用类型,每个函数就是Function类型的实例,都与其他引用类型具有相同的属性和方法。函数为对象,所以函数名只是指向函数对象的指针

声明变量有两种方式。看例子吧。

      function sum(num1,num2){     //函数声明来定义函数
            return num1+num2
      }

      var sum=function(num1,num2){  //函数表达式定义函数
            return num1+num2
      }

      //函数名仅仅为指针;所以也能理解上面所说的函数没有重载
      function one(num1,num2){
           return num1+num2
      }
      var two=one
      var one=null
      console.log(two(1,2))    //3  即使one为null

函数声明和函数表达式之间的相爱相杀

解析器对他们两个态度可是不同的

对于函数声明,解析器会优先读取,对其有个函数声明提升的过程(function declaration hoisting)

对于函数表达式,解析器可就不会优先了,只有读取到其,才会被解释执行

      console.log(sum(1,2))        //3
      function sum(num1,num2){     
            return num1+num2
      }

      console.log(another(1,2))    //another is not a function
      var another=function(num1,num2){
            return num1+num2
      }

当然还有构造函数法,不推荐使用,导致代码的二次解析,一次是常规js的,一次是构造函数的

 

也就是函数可以作为值传参

     function sum(someFunction,value){        //基本的函数中的嵌套
             return someFunction(value)
     }

     function multiplys(num){                 //内部的函数
            return num*num
     }

     console.log(sum(multiplys,2))            //调用函数,访问内部函数的指针,不需要()调用

利用作为值得函数,可以按照某一属性对数组进行排序

     function compare(value){                 //想要通过比较obj的属性,这里的value只是参数,没有被实例化;而在简单的数组中都已经被实例化了
           return function(obj1,obj2){
              var value1=obj1[value]
              var value2=obj2[value]
              return value1-value2
           }
     }

     var data=[{name:"double",age:24},{name:"zom",age:23},{name:"mike",age:32}]
     data.sort(compare("age"))
     console.log(data)         //23,,24,32来排序

2、函数内部的属性

在函数的内部,一般有两个对象

this对象:this引用的是函数执行的环境对象,即this值(在全局环境中,this则代表的是window)

arguments对象:类数组对象,保存函数参数;有个callee属性,此属性是个指针,指向拥有arguments对象的函数

ES5规定了另个一个函数对象的属性caller,保存着调用当前函数的函数引用,在全局作用域中调用当前函数则为null

     //递归函数
     function sum(num){
          if(num<=1){
              return 1
          }
          else{
              return num*arguments.callee(num-1)     //消除紧紧耦合,保证完成递归函数,所以用callee属性
          }
     }
     var summ=sum;
     sum=null
     console.log(summ(10))


    //this
    window.color="red"

    function sayColor(){
         console.log(this.color)
    }

    sayColor()                    //red

    var another={color:"blue"}   
    another.putColor=sayColor     //函数名只是个指针
    another.putColor()            //blue


  //函数对象属性caller
  function outer(){
      inner()
  }
 /*  function inner(){
      console.log(inner.caller)
  }*/
  function inner(){
      console.log(arguments.callee.caller)    //减少耦合
  }
  outer()             //outer()函数

3、函数的属性和方法

每个函数有两个属性

length属性:表示函数的参数名个数

prototype属性:保存引用类型所有实例方法,不可枚举,用for-in无法实现

每个函数都包含两个非继承的方法;都是在特定的作用域中调用函数,实际等于设置函数体内this对象的值

apply()方法:接受两个参数,一为在其中运行函数的作用域,一为参数数组(Array的实例或者arguments对象)

call()方法:接受的第一个参数是this值没变化,第二个不是数组了,直接传递给参数即可,看例子吧

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

   function oneSum(num1,num2){
       return sum.apply(this,arguments)         //arguments对象
   }
   function twoSum(num1,num2){
       return sum.apply(this,[num1,num2])       //数组
   }

   console.log(oneSum(1,2))
   console.log(twoSum(1,2))

   function three(num1,num2){
       return sum.call(this,num1,num2)          //参数直接传递
   }
   console.log(three(1,2,3))   
  
  //apply()和call()方法可以扩充函数的作用域
  window.color="red"
  var one={color:"red"}

  function sayColor(){
      console.log(this.color)
  } 
  sayColor()                  //red

  sayColor.call(this)         //red
  sayColor.call(window)       //red
  sayColor.call(one)          //blue   这里的作用域为one中的了,不需要再将函数放到one中等操作

ES5规定还规定一个方法bind(),创建一个函数实例,其this值被绑定到传给bind()函数的值,

  window.color="red"
  var one={color:"blue"}

  function sayColor(){
      console.log(this.color)
  }

  var another=sayColor.bind(one)     //ES5的函数方法,创造一个函数实例了,并且绑定的this值传递给函数了
  another()                          //blue

 

posted @ 2018-02-05 18:47  决起而飞  阅读(381)  评论(0编辑  收藏  举报