JS引用类型中的Function类型——函数属性和方法【this,arguments对象;apply(),call方法】

一,了解函数

1,函数实际是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法,由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
2,函数没有重载,当声明了两个同名函数时结果会是后面的函数覆盖前面的函数。

二,函数的内部属性

在函数内部,有两个特殊的对象:arguments和this
函数内部的arguments对象
1,arguments是一个类数组对象,包含着传入函数中的所有参数,它的主要作用是保存函数参数。
2,arguments的callee属性:该属性是一个指针,指向拥有这个arguments对象的函数(即arguments是哪个函数的,这个属性就指向谁)
看下面的阶乘函数用到的递归算法,理解callee属性的作用

function calleeTest(num){
       if(num <= 1) {
           return 1;
       }else{
           return num * calleeTest(num-1);
       }
   }
    var truecalleeTest = calleeTest;
    calleeTest = function(){
        return 0;
    };
   console.log(truecalleeTest(5));//0
   /*这样定义是没有问题的,但是函数的执行与函数名紧紧的耦合在了一起,将函数名修改为truecalleeTest以后,函数体内的calleeTest名字没有被改变,所以会执行后面返回零的函数*/

   function calleeTest(){
       if(num <= 1){
           return 1;
       }else{
           return num * arguments.callee(num - 1);
       }
   }
  var truecalleeTest = calleeTest;
    calleeTest = function(){
        return 0;
    };
   console.log(truecalleeTest(5));//120
/*在这次的函数体内就没有再使用函数名calleeTest,无论引用函数时使用什么函数名,都可以保证正常的递归调用*/

函数内部的this对象
1,this引用的是函数执行的环境对象,也可以说是this值(当在网页的全局作用域中调用函数时,this对象引用的是window。
以下代码中this就指向了不同对象

 window.color = "yellow";
    var obj = {
        color:"red"
    };
    function showColor(){
        alert(this.color);
    }
    showColor();//yellow
    /*showColor函数是在全局作用域中定义的,它引用了this对象,由于在调用之前this的值并不确定,因此this在代码执行过程中可能会引用不同对象。当在全局作用域中调用showColor()时 this引用的是全局对象window。即this.color求值转化成window.color求值*/
    obj.addColor = showColor;
    obj.addColor();//red
    /*当把这个函数赋给对象obj的addColor属性时并调用obj.addColor()时,this引用的
    对象是obj。即this.color求值转化成obj.color求值*/

注意:函数的名字仅仅是一个包含指针的变量而已,因此在上面的代码中即使是在不同的环境中执行,但是在代码obj.addColor = showColor之后,代表着全局的showColor()函数和obj.addColor()指向的仍然是同一个函数

函数对象的caller属性
该属性中保存着调用当前函数的函数的引用,若是在全局作用域中调用当前函数,它的值为null。例如:

 function outer(){
       inner();
   }
   function inner(){
       alert(inner.caller);
   }
   outer();

上面代码中outer函数引用了inner函数,inner函数里面的inner.caller保存着调用inner函数的outer函数的引用,即指向的的是outer函数。所以结果是会出现如下的显示outer函数内容的警示框
在这里插入图片描述

当然为了实现更松散的耦合,可以使用arguments.callee.caller来访问相同的信息,代码如下:

 function outer(){
       inner();
   }
   function inner(){
       alert(arguments.callee.caller);//arguments.callee指向arguments所属函数inner,即还是inner.caller
   }
   outer();
三,函数属性

————因为函数是对象,所以函数也有属性和方法,每个函数都包含两个属性:length和prototype
1,length属性
表示函数希望接收的命名参数的个数,如下:

 function funA(name){
      alert(name);
  }
  function funB(num1,num2){
      alert(num1 + num2);
  }
  function funC(){
      alert("hello");
  }
  console.log(funA.length);//1
  console.log(funB.length);//2
  console.log(funC.length);//0

2,prototype属性
对于ECMAScript中的引用类型而言,prototype是保存它们所有实列方法的真正所在,诸如toString()和valueOf()等方法实际上都是保存在prototype名下,只不过是通过各自对象的实例进行访问。

五,函数方法

————每个函数都包含了两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的this对象值
1,apply方法
接收连个参数:在其中运行函数的作用域,参数数组。其中第二个参数可以是Array的实例,也可以是arguments对象。如下:

 function sum(num1,num2){
     return num1 + num2;
 }
 function callSum1(num1,num2){
     return sum.apply(this,arguments);//传入arguments对象
 }
 function callSum2(num1,num2){
     return sum.apply(this,[num1,num2]);//传入数组
 }
 console.log(callSum1(10,20));//30
 console.log(callSum2(10,20));//30

上面代码中apply方法的第一个参数传入this作为this值,又因为是在全局作用域中调用的,所以传入的就是window对象。所以将函数sum里面的this指向了window

2,call()方法:
第一个参数还是this值,其余参数都只能直接的一个一个传递给参数,即逐个列举出来。如下:

function sum(num1,num2){
     return num1 + num2;
 }
 function callSum(num1,num2){
     return sum.call(this,num1,num2);//此处是逐个传递参数num1,num2
 }
 console.log(callSum(10,20));//30

3,以下讨论的是这两个方法的重点,apply()和call()方法真正强大的地方是扩大函数赖以运行的作用域

window.name = "I am the window";
 var obj = {
     name:"I am the obj"
 };
 function myAge(){
     alert(this.name);
 }
 myAge();//I am the window;执行函数myAge()
 myAge.apply(this);//I am the window;利用apply()将myAge函数里面的this指向了this对象,而在全局环境下this默认指向window
 myAge.apply(window);//I am the window;利用apply()函数将myAge函数里面的this指向了window对象
 myAge.apply(obj);//I am the obj;利用apply()函数将myAge函数里面的this指向了obj

3,ECMAScript5还定义了一个函数的方法:bind()方法
该方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。如下:

window.food = "vegetables";
var eatFood = {
     food:"meat",
     eat:function(){
         alert(this.food)
     }
 };
 function showFood(){
     alert(this.food);
 }
 var food = showFood.bind(eatFood);//作用和前面讲的方法一样,将showFood函数里面的this值指向了eatFood对象
 food();//meat

猜你喜欢

转载自blog.csdn.net/Sunday97/article/details/84974710