zoukankan      html  css  js  c++  java
  • 函数Function

        函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

    一、定义函数的方法:

    1.函数声明

    function sum(num1,num2){}

    2.函数表达式

    var sum=function(num1,num2){}

    使用函数表达式定义时,没有必要使用函数名,但也可以是var sum=function ab(num1,num2){}

    使用不带圆括号的函数名是访问函数指针,而非调用函数。

    3.区别

    解析器会率先读取函数声明,并使其在执行任何代码之前可用;至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

    二、函数没有重载

    JS中函数没有重载,在创建第二个函数时,实际上覆盖了第一个函数。

    三、作为值的函数

    函数本身就是变量,所以函数也可以作为值来使用。可以像传递参数一样把一个函数传递给另一个函数,而且也可以将一个函数作为另一个函数的结果返回。

    四、函数内部属性

    1.arguments

    在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数。arguments对象和数组类似,因此可以通过方括号访问,length确定传递进来的参数个数。arguments[0]

    另外arguments的值永远与对应命名参数的值保持同步。

    function doAdd(num1,num2){

      arguments[1]=10;

      alert(arguments[0]+num2);//num2每次都被重写为10

    }

    这个对象还有一个属性callee,该属性是一个指针,指向拥有这个arguments对象的函数。

    function factorial(num){

      if(num<=1){

        return 1;

      }else{

        return num*arguments.callee(num-1);

      }

    }

    2.另一个函数对象的属性caller

    这个属性保存着调用当前函数的函数的引用,如果是在全局作用域中调用当前函数,它的值为null。

    function outer(){

      inner();

    }

    function inner(){

      alert(inner.caller);//弹出调用inner的函数的引用,也就是outer,因此会输出function outer(){inner();}

    }

    为了实现更松的耦合,可以这样调用

    function inner(){

      alert(arguments.callee.caller);

    }

    五、函数的属性和方法

    每个函数都包含两个属性length和prototype; length属性表示函数希望接受的命名参数的个数。

    function sayName(num1,num2){}

    alert(sayName.length)//2

    prototype是保存函数所有实例方法的真正所在。不可枚举,无法使用for-in发现。

    每个函数都包含两个非继承而来的方法:apply()和call()

    用途:在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

    扩充函数赖以运行的作用域。

    1.apply()

    接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。第二个参数可以是Array的实例,也可以是arguments对象。

    2.call()

    作用同apply,区别仅在于接收参数的方式不同。第一个参数相同,第二个参数是直接传递给函数,也就是说传递给函数的参数必须逐个列举出来。

    3.bind()

    其this值会被指定给传给bind()函数的值。

    window.color='red';
    
    var o={color:'blue'};
    
    var b={color:'yellow'};
    
    function sayColor(){
    
      alert(this.color);
    
    }
    
    var osaycolor=sayColor.bind(o);
    
    var bsaycolor=sayColor.bind(b);
    
    osaycolor()//'blue'
    
    bsaycolor()//'yellow'

    4.toLocalString()  toString() valueOf()

    始终返回函数的代码。

    六、理解apply() call()

    经常会这样定义:
      
    function cat(){
      }
    cat.prototype={
      food:"fish",
      say: function(){
         alert("I love "+this.food);
      }
    }
    
    var newCat = new cat();
    newCat.say();

    但是如果我们有一个对象newDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用newCat的say方法:
    newCat.say.call(newDog);
    cat.prototype.say.call(newDog);

    所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。

    用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:
    var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));
    这样domNodes就可以应用Array下的所有方法了。
     

    call和apply可以用来重新定义函数的执行环境,也就是this的指向。通过一个操作DOM的例子来理解。

    
    
    function changeStyle(attr, value){
        this.style[attr] = value;
    }
    var box = document.getElementById('box');
    window.changeStyle.call(box, "height", "200px");

    call中的第一个参数用于指定将要调用此函数的对象,在这里,changeStyle函数将被box对象调用,this指向了box对象,如果不用call的话,程序报错,因为window对象中没有style属性。
    apply的用法:

    window.changeStyle.apply(box, ['height', '200px']);
     
    1. 
    function add(a,b){  
        alert(a+b);  
    }  
    function sub(a,b){  
        alert(a-b);  
    }  
    add.call(sub,3,1); //  4

    2.

    function Animal(){ 
      this.name = "Animal"; 
      this.showName = function(){ 
        alert(this.name); 
      } 
    }
    
    function Cat(){ 
      this.name = "Cat"; 
    } 
    
    var animal = new Animal(); 
    var cat = new Cat(); 

    //通过call或apply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。
    animal.showName.call(cat,",");   //Cat
    //animal.showName.apply(cat,[]);  //Cat

    3.实现继承

    function Animal(name){ 
      this.name = name; 
      this.showName = function(){ 
        alert(this.name); 
      }
    
      this.hi=function(){// 注意这里必须是this引用才能继承,否则cat.hi()时,会报错,hi不是一个函数 
    
        alert("hello "+this.name);
    
      } 
    } 
    
    function Cat(name){ 
      Animal.call(this, name); 
    } 
    
    var cat = new Cat("Black Cat"); 
    cat.showName();//Black Cat
    
    cat.hi();//hello Black Cat

    4.多重继承

    function Class10(){
    
      this.showSub = function(a,b){
        alert(a-b);
      }
    }
    
    function Class11(){
    
      this.showAdd = function(a,b){
        alert(a+b);
      }
    }
    
    function Class2(){
    
      Class10.call(this);
      Class11.call(this);
    }
    
    var c2=new Class2();
    
    c2.showSub(10,3)//7
    
    c2.showAdd(10,3)//13
  • 相关阅读:
    idea解决Maven jar依赖冲突(四)
    代码规范:idea上添加阿里巴巴Java开发插件
    一起MySQL时间戳精度引发的血案
    JVM Code Cache空间不足,导致服务性能变慢
    通过SOFA看Java服务端如何实现运行时的模块化
    谈谈我对SOFA模块化的理解
    谈谈我对SOFA模块化的理解
    一文谈尽边缘计算
    JVM调优实战:G1中的to-space exhausted问题
    JVM调优实战:G1中的to-space exhausted问题
  • 原文地址:https://www.cnblogs.com/YangqinCao/p/5411758.html
Copyright © 2011-2022 走看看