函数



1.函数的定义



(1)function 函数名(x){ 函数执行体; }



(2)var 函数名=function(x){ 函数执行体; };



这种方法说明,在javascript中,函数就是一种对象,也就是说,函数也是一种数据类型,参数列表相当于函数的入口,return相当于函数的出口。



如:var abs = function (x) { 
 
 
 

       if (x >= 0) { 
 
 
 

           return x; 
 
 
 

       } else { 
 
 
 

           return -x; 
 
 
 

       } 
 
 
 

   }; 
 
 
 

   function (x) { ... }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。 
 
 
 

   上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;,表示赋值语句结束。



2.函数调用



由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数。



abs(10, 'blablabla'); // 返回10 
 
 
 

   3.arguments 
 
 
 

   JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array: 
 
 
 

   function foo(x) { 
 
 
 

       alert(x); // 10 
 
 
 

       for (var i=0; i<arguments.length; i++) { 
 
 
 

           alert(arguments[i]); // 10, 20, 30 
 
 
 

       } 
 
 
 

   } 
 
 
 

   foo(10, 20, 30); 
 
 
 

   实际上arguments最常用于判断传入参数的个数。你可能会看到这样的写法: 
 
 
 

   // foo(a[, b], c) 
 
 
 

   // 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null: 
 
 
 

   function foo(a, b, c) { 
 
 
 

       if (arguments.length === 2) { 
 
 
 

           // 实际拿到的参数是a和b,c为undefined 
 
 
 

           c = b; // 把b赋给c 
 
 
 

           b = null; // b变为默认值 
 
 
 

       } 
 
 
 

       // ... 
 
 
 

   } 
 
 
 

   要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。 
 
 
 

   4.rest 
 
 
 

   function foo(a, b, ...rest) { 
 
 
 

       console.log('a = ' + a); 
 
 
 

       console.log('b = ' + b); 
 
 
 

       console.log(rest); 
 
 
 

   } 
 
 
 

     
 
 
 

   foo(1, 2, 3, 4, 5); 
 
 
 

   // 结果: 
 
 
 

   // a = 1 
 
 
 

   // b = 2 
 
 
 

   // Array [ 3, 4, 5 ] 
 
 
 

     
 
 
 

   foo(1); 
 
 
 

   // 结果: 
 
 
 

   // a = 1 
 
 
 

   // b = undefined 
 
 
 

   // Array [] 
 
 
 

   从运行结果可知,传入的参数先绑定a、b,多余的参数以数组形式交给变量rest,所以,不再需要arguments我们就获取了全部参数。 
 
 
 

   如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)。 
 
 
 

   方法 
 
 
 

   1.在一个对象中绑定函数,称为这个对象的方法。如: 
 
 
 

   var xiaoming = { 
 
 
 

       name: '小明', 
 
 
 

       birth: 1990, 
 
 
 

       age: function () { 
 
 
 

           var y = new Date().getFullYear(); 
 
 
 

           return y - this.birth; 
 
 
 

       } 
 
 
 

   }; 
 
 
 

   xiaoming.age; // function xiaoming.age() 
 
 
 

   xiaoming.age(); // 今年调用是25,明年调用就变成26了 
 
 
 

   2.this 
 
 
 

   在一个方法内部,this是一个特殊变量,它始终指向当前对象,也就是xiaoming这个变量。所以,this.birth可以拿到xiaoming的birth属性。如果拆开写的话: 
 
 
 

   function getAge() { 
 
 
 

       var y = new Date().getFullYear(); 
 
 
 

       return y - this.birth; 
 
 
 

   } 
 
 
 

     
 
 
 

   var xiaoming = { 
 
 
 

       name: '小明', 
 
 
 

       birth: 1990, 
 
 
 

       age: getAge 
 
 
 

   }; 
 
 
 

     
 
 
 

   xiaoming.age(); // 25, 正常结果 
 
 
 

   getAge(); // NaN 
 
 
 

     
 
 
 

   如果单独调用函数getAge(),此时,该函数的this指向全局对象,也就是window。 
 
 
 

   3.apply 
 
 
 

   虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向的! 
 
 
 

   要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。 
 
 
 

   用apply修复getAge()调用: 
 
 
 

   function getAge() { 
 
 
 

       var y = new Date().getFullYear(); 
 
 
 

       return y - this.birth; 
 
 
 

   } 
 
 
 

     
 
 
 

   var xiaoming = { 
 
 
 

       name: '小明', 
 
 
 

       birth: 1990, 
 
 
 

       age: getAge 
 
 
 

   }; 
 
 
 

     
 
 
 

   xiaoming.age(); // 25 
 
 
 

   getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空 
 
 
 

   另一个与apply()类似的方法是call(),唯一区别是: 
 
 
 

   apply()把参数打包成Array再传入; 
 
 
 

   call()把参数按顺序传入。