js引用类型之函数

125 阅读4分钟
函数的定义
  • 使用函数声明语法定义: function methodName(){ }
    //先调用
    test();
    //后定义
    function test(){
        console.log("先执行了");
    }
    //也能执行,打印结果为
    先执行

注意:解析器会率先读取函数声明,并使其在执行任何代码之前可用(可以访问).

  • 使用函数表达式语法定义: var methodName=function(){ }
    test();
    var test=function(){
        console.log("先执行了");
    }
    //打印结果报错
    TypeError: test is not a function

注意: 函数表达式只有解析器执行到它所在的代码行才会被解析执行。

  • 综合使用语法定义: var methodName= function methodName(){ } 注意:两个methodName不一致,但只有前一个可以使用 。
   var test=function another(){
       console.log("先执行了");
   }
   test();
   //打印结果
   先执行了
函数的重载

定义的两个函数名相同的函数,只会后者覆盖前者,并不会达到重载的效果

   function one() {
     console.log("执行第一个");
   }
   function one(data) {
     if (data == null) {
       console.log("没有");
     } else {
       console.log("数量为:" + data + "个");
     }
   }
   one();
   one(10);
   //打印结果
   没有
   数量为:10
函数可作为参数传入另一个函数,也可作为返回值返回
  • 作为参数传入: 语法格式
  function callSomeFunction(someFunction, someArgument) {
    return someFunction(someArgument);
  }

例子

  function one(a, b) {
    return a + b;
  }
  //以其他函数和参数名定义另一个函数
  function two(method, param1, param2) {
    return method(param1, param2);
  }
  var result = two(one, 2, 3);
  console.log("相加后的值" + result);
  //以要传入的函数和参数名定义
  function two(one, a, b) {
    return one(a, b);
  }
  var result1 = two(one, 2, 3);
  console.log("相加后的值" + result1);
  //打印结果
  相加后的值5
  相加后的值5
  • 作为返回值返回
   function compareToParam(param){
       return function specialCompare(object1,object2){
           var value1=object1[param];
           var value2=object2[param];
           if(value1<value2){
               return -1;
           }else if(value1=value2){
               return 0;
           }else{
               return 1;
           }
       };
   }
   var data=[{name:"zhangsan",age:28},{name:"lisi",age:14},{name:"wanger",age:18}];
   var arr=data.sort(compareToParam("age"));
   console.log(arr);
   //打印结果
   [
     { name: 'lisi', age: 14 },
     { name: 'wanger', age: 18 },
     { name: 'zhangsan', age: 28 }
   ]

注意:此处不能用.的方式获取对象的属性值

扩展:用.[]获取对象属性值的区别 . 适用于对象直接引用属性名,[]既可以直接传入属性名,也可以传入其他中间变量

   var data = [{
     name: "zhangsan",
     age: 28
   }, {
     name: "lisi",
     age: 14
   }, {
     name: "wanger",
     age: 18
   }];
  console.log(".直接引用可以:"+data[0].name);
  var age1="age";
  console.log(".间接调用不可以:"+data[0].age1);
  console.log("[]间接调用可以:"+data[0][age1]);
  //打印结果
  .直接引用可以:zhangsan
  .间接调用不可以:undefined
  []间接调用可以:28
函数的特殊对象

正常递归函数,不能随意对函数变量重新赋值,否则得不到预计的结果

  function factorial(num) {
     if (num == 1) {
       return 1;
     } else {
       return num * factorial(num - 1);
     }
   }
   console.log("未对函数进行重新赋值:"+factorial(2));
   var trueApplay = factorial;
   //重新对函数变量赋值
   factorial = function () {
     return 0;
   }
   console.log("对函数进行重新赋值:"+trueApplay(2));
   //打印结果
   未对函数进行重新赋值:2
   对函数进行重新赋值:0

函数内部特殊对象有argumentsthis,而arguments有一个重要属性:callee

  • callee属性是一个指针指向拥有arguments对象的函数,从而不受函数名的影响,降低耦合性。
  function factorial(num) {
     if (num == 1) {
       return 1;
     } else {
       return num * arguments.callee(num - 1);
     }
   }
   console.log("未对函数进行重新赋值:"+factorial(2));
   var trueApplay = factorial;
   factorial = function () {
     return 0;
   }
   console.log("对函数进行重新赋值:"+trueApplay(2));
   //打印结果
   未对函数进行重新赋值:2
   对函数进行重新赋值:2

注意:js中通常可以把函数当做一个对象来看待,多个变量可以指向同一函数。

  • this : 引用的是调用它的环境对象
    color = "red";
    var fruit = {
      name: "apple",
      color: "blue"
    };
    function sayColor() {
      return this.color;
    }
    console.log("window环境调用此方法:" + sayColor());
    //给对象添加一个方法
    fruit.sayColor = sayColor;
    console.log("fruit对象调用此方法:" + fruit.sayColor());
    //打印结果
    window环境调用此方法:red
    fruit对象调用此方法:blue

总结: sayColor函数引用的this对象,会在执行过程中指向不同的对象。但sayColorfruit.sayColor指向的是同一个函数。

函数的属性和方法

属性:lengthprototype, 方法: applycall

  • 参数个数lenth
    function one(a){
        console.log(a);
    }
    function two(a,b){
        console.log(a+b);
    }
    function three(){
    }
    console.log("one参数个数: "+one.length);
    console.log("two参数个数: "+two.length);
    console.log("three参数个数: "+three.length);
    //打印结果
    one参数个数: 1
    two参数个数: 2
    three参数个数: 0
  • 每个函数都包含三个继承方法applycallbind
  1. apply传入两个参数:第个是运行函数的作用域(如this),第个参数为数组或者arguments对象
    function sum(num1, num2) {
      return num1 + num2;
    }
    function callSum1(num1, num2) {
      return sum.apply(this, arguments); 
    }
    function callSum2(num1, num2) {
      return sum.apply(this, [num1, num2]);  
    }
    console.log(callSum1(10, 10));
    console.log(callSum2(10, 10)); 
    //打印结果
    20
    20
  1. call传入的第个参数为运行函数的作用域其余参数可由另一个函数直接传入。
    function sum(a,b){
        return a+b;
    }
    function sum1(a,b){
        return sum.call(this,a,b);
    }
    console.log(sum1(10,10))
    //打印结果
    20
  1. call另一个重要作用是扩充函数的作用域,减少函数方法的耦合性
    var fruit = {
      name: "apple",
      color: "blue"
    };
    function sayColor() {
      return this.color;
    }
    console.log(sayColor.call(fruit));
    //打印结果
    blue
  1. bind.的作用效果一致,前者是方法绑定对象,后者是对象绑定方法
    var fruit = {
      name: "apple",
      color: "blue"
    };
    function sayColor() {
      return this.color;
    }
    var fruitColor=sayColor.bind(fruit);
    console.log(fruitColor());
    //打印结果
    blue