动态调用函数:再解apply和call

在开发过程中,特别是复杂控件封装时,常会用到动态调用函数。那么动态调用函数实则就是利用call和apply方法来实现的。

call和apply的区别

其实call和apply基本没有什么太大的区别,只是传递给函数的参数方式不同罢了。apply是以数组的形式进行的参数传递,而call方法可以同时传递多个参数。利用apply以数组的形式进行参数传递的特性,在很多时候能够使我们的程序更优美。比如下面的代码:

    function max() {
        var m = Number.NEGATIVE_INFINITY;
        for (var i = 0, l = arguments.length; i < l; i++) {
            if (arguments[i] > m) m = arguments[i];
        }
        return m;
    }
    var a = [1, 33, 32, 12, 45, 30, 11, 2];
    var aMaxValue = max.apply(Object, a);
    alert("数组中最大数值为:"+aMaxValue);
当然如果是获取最大值,利用apply的特性,还有个更简单的方式:

    var value = Math.max.apply(Object,a);
    alert("数组中最大数值为:"+aMaxValue);
直接利用Math对象的max方法。由于该方法能够接收多个参数,但是不能接收数组,而我们又不想遍历数组。那么用apply是最佳的选择了。

改变对象内部指针

call和apply主要能力就是可以改变对象内部指针。说白点就是,可以通过指定的对象来调用方法,从而完成方法中this对象的改变(变成指定的对象)。看看下面的列子,就充分的说明了call和apply的这一强大功能。

    var x = "全局";

    function aFun(){
        this.x = "a方法";
    }

    function bFun(){
        this.x = "b方法";
    }
    function cFun(){
    }
    function doFun(){
        alert(this.x);
    }
    doFun(); //全局
    doFun.call(window);// 由于传入的是window,因此doFun中的this指向的就是window,那么this.x此时等价于window.x  ,因此输出“全局”
    doFun.call(new aFun());//由于传入的是aFun对象,因此doFun中的this指向的就是aFun,那么this.x此时等价于aFun.x,因此输出“a方法”
    doFun.call(new bFun());//由于传入的是bFun对象,因此doFun中的this指向的bFun,那么this.x此时等价于bFun.x,因此输出“b方法”
    doFun.call(new cFun());//由于传入的是cFun对象,因此doFun中的this指向的就是cFun,那么this.x此时等价于cFun.x,因此输出“undefined”

利用call和apply完成继承

在js里面其实也是可以玩对象继承的。我们可以利用call和apply能够改变对象内部指针的能力,来实现继承。

    //车类
    function Car (){
        this.footBrake = 1;
        this.getFootBrakeCount = function(){
            alert("车子"+this.footBrake+"个脚刹");
        }
    }

    //教练车
    function CoachCar(){
        Car.call(this);
        this.footBrake = 2;
    }
    
    var p = new Car();
    p.getFootBrakeCount(); //车子有1个脚刹

    var d = new CoachCar();
    d.getFootBrakeCount();//车子有2个脚刹
动态改变函数

 function r(x){
        return (x);
    }
    function f(x){
        x[0] = x[0]+">";
        return x;
    }
    function o(){
        var temp = r;
        r = function(){
            return temp.apply(this,f(arguments));
        }
    }
function a(){
    o();
    alert(r("="))
}
    for(var i= 0;i<2;i++){
        a();
    }
//第一次输出:=>
//第二次输出:=>>
这段代码的关键就是在于r方法在不断的变化。for循环中a()执行两次,其实r()方法执行了三次。原因就在于r()在不停的变化。通过apply 方法的使用 和 对象是引用类型 这两个关键点可以很轻松明白为什么第二次输出是=>>。

你可能感兴趣的:(call,函数动态调用,allpy)