1. 程式人生 > >apple,call和bind的理解

apple,call和bind的理解

可變 有一個 apple 屬性和方法 方法 存在 windows delete 意思

apply call 和 bind 函數的理解

提供自己手動綁定this的方法

函數的調用

首先在js裏函數調用有4種模式:方法調用、正常函數調用、構造器函數調用、apply/call 調用。同時,無論哪種函數調用除了你聲明時定義的形參外,還會自動添加2個形參,分別是 this 和 arguments。

this的自動綁定

  1. 方法調用 this 綁定的就是對象本身
  2. 如果你在一個函數前面帶上 new 關鍵字來調用,那麽 js 會創建一個 prototype 屬性是此函數的一個新對象,同時在調用這個函數的時候,把 this 綁定到這個新對象上。當然 new 關鍵字也會改變 return 語句的行為
  3. 函數的正常調用,也是會默認指定this。 通常是windows

this的手動綁定

在js裏,我們編寫的函數,也是屬於對象, 由系統定義好的Function函數來創建出來的。所以函數都會有一個共有的原型對象,Fuction.prototype.而這個原型自帶有好幾個屬性和方法,其中就有這裏困惑的 bind、call、apply方法。
而三個函數有一個共同的特點就是可以設置this的值。上面的3種函數調用方式,你可以看到,this都是自動綁定的,沒辦法由你來設,當你想設的時候,就可以用他們了

apply

它讓我們構造一個參數數組(函數運行所需的參數)傳遞給函數,同時可以自己來設置 this 的值,這就是它最強大的地方,。apply 函數接收 2 個參數,第一個是傳遞給這個函數用來綁定 this 的值,第二個是一個參數數組。

call

它允許我們傳入不定長參數(函數運行所需的參數),同時可以自己來設置 this 的值。 只是參數和apply不一樣。

bind

bind() 函數,上面講的無論是 call() 也好, apply() 也好,都是立馬就調用了對應的函數,而 bind() 不會, bind() 會生成一個新的函數,bind() 函數的參數跟 call() 一致,第一個參數也是綁定 this 的值,後面接受傳遞給函數的不定參數。 bind() 生成的新函數返回後,你想什麽時候調就什麽時候調

用法

apply 和 call

這兩個方法的用途都是在特定的作用域中調用函數,實際上等於函數體內this對象的值, 他們會立即執行

  1. 作用在方法上的理解
    當對象o上不存在方法f時,我們通過call去指定 this時,就相當於在o上新增一個f方法,然後調用完成之後刪除。
    f.call(o); f.apply(o); // 假設o中不存在m方法,則等價於: o.m = f; //將f存儲為o的臨時方法 o.m(); //調用它,不傳入參數 delete o.m; //將臨時方法刪除

    實例:

    window.color = "red";
    var o = {color: "blue"};
    function sayColor(){
        console.log(this.color); // 打印調用對象的顏色值
    }
    sayColor();   // 打印 全局對象window 的color值
    sayColor.call(window);  // 打印 全局對象window 的color值
    sayColor.call(this);// 打印 全局對象window 的color值
    sayColor.call(o); // 打印 o 對象的 color值
    console.log(o);
    // sayColor.call(o)等價於:
    // o.sayColor = sayColor;
    // o.sayColor();   //blue
    // delete o.sayColor;
  1. 作用於類上的理解
    a對象的方法應用到b對象上(函數apply的意思正好說明符合這樣理解:a對象應用到b對象上去)
    a對象既然添加到b對象上了。那麽b對象自然就擁有了a對象所有的內容。所以,b對象就繼承了a對象了。 和C++的繼承有點相似
        function class1(){
            this.name = function(x){
                alert("我是class1的name(x)方法"+",我是class1name函數的參數(" + x + ")");
            }
        }

        function class2(){
            class1.call(this); // this 就是class的對象
        }

        var c1 = new class2();
        //c1.name(20);
        console.log(c1); // 
        class2();
  1. 看參數的不同使用
    function sum(num1, num2){
        console.log("num1:" + num1 + "  num2:" + num2);
        return num1 + num2;
    }
    function applySum1(num1, num2){
        return sum.apply(this,arguments); 
    }
    function applySum2(num1, num2){
        return sum.apply(this,[num1,num2]);
    }
    function callSum(num1, num2){
        return sum.call(this,num1,num2);
    }
    console.log(callSum(1,2));

bind

bind() 函數,上面講的無論是 call() 也好, apply() 也好,都是立馬就調用了對應的函數,而 bind() 不會, bind() 會生成一個新的函數,bind() 函數的參數跟 call() 一致,第一個參數也是綁定 this 的值,後面接受傳遞給函數的不定參數。 bind() 生成的新函數返回後,你想什麽時候調就什麽時候調

var m = {
            "x" : 1
    }
function foo(y){
    console.log(this.x + y);
}
foo.apply(m, [5]); // apply 接收數組 會自動展開
foo.call(m,5);  // call 接受可變參數
var foo1 = foo.bind(m);
foo1(5);

總結

其實這裏的this改變你可以認為,是給對象添加了一個方法,之後刪除。可能這樣好理解點。而對於參數而言,其實就是一個要求數組,兩個要是不定長參數,視情況用,還有就是bind返回的是一個新函數,不會立即執行。

apple,call和bind的理解