1. 程式人生 > >JavaScript中apply bind call的異同(重點講解call方法)

JavaScript中apply bind call的異同(重點講解call方法)

JavaScript中若想改變this的指向那就必須用到apply call bind 方法,但其中三個方法有他們的區別

 apply()

apply():第一個引數將代替function類裡的this物件,第二個引數是陣列,將他作為引數傳給function的arguments
function a(){
       this.name = 'a';
        this.show = function(){alert(this.name)};
    }
    function b() {
        this.name = 'b';
    }
    var B = new
b(); a.apply(B); B.show(); 這時輸出a,這是因為apply方法中將this的指標改為了b,在functionb.name = 'a', b.show = function(){alert(this.name)};所以當再次呼叫B.show()時輸出的是a function A(a,b) { this.a = a; this.b = b; } function B() { A.apply(this,[1,2]); this.c = 3; } var
s = new B(); alert(s.a+","+s.b+","+s.c); 這時輸出123,這是因為在B函式中用apply方法將B的this給了a的this,將後面的12作為引數傳給了A,這時給B的this分別添加了a和b屬性,所以再次輸出的時候B中會存在a,b,c三種屬性。

 call ()

call():call方法和apply方法類似只不過傳入引數方法不同call方法中第二個引數不是陣列,而是從第二個開始其餘引數直接傳給函式的arguments
,f  function a(){
        this.name = 'a';
        this
.show = function(){alert(this.name)}; } function b() { this.name = 'b'; } var B = new b(); a.call(B); B.show(); 在這裡我們將之前的apply方法改為了call方法,執行之後的結果和方法與apply方法相同 function A(a,b) { this.a = a; this.b = b; } function B() { A.call(this,1,2); this.c = 3; } var s = new B(); alert(s.a+","+s.b+","+s.c); 在這裡我們將B函式中的apply方法改為了call方法,執行之後的結果和方法與apply方法相同,但是在這裡call方法傳入的引數發生了變化,apply是傳入陣列,而call方法是直接將引數傳入 有了之前的鋪墊,那麼我們現在繼續深入一下 function A(a,b) { this.a = a; this.b = b; } function B() { this.a = 5; this.c = 3; A.call(this,1,2); } var s = new B(); alert(s.a+","+s.b+","+s.c); 這時大家猜測一下輸出是什麼,是523嗎? 不,這時繼續輸出123,為什麼呢?這時因為給B呼叫了A的call方法,使A的this指標指向了B,雖然我們定義了B的a為5,但是在呼叫call方法之後又將B的a重寫為了1 function A(){ this.show = function(){alert(this.name)} } function B(){ this.name = 'b'; } var C = new A(); var D = new B(); C.show.call(D);//b alert(D.show);//undefined 這段程式碼中,讓C.show中的this指向了D,但是並沒有給D寫入C.show,所以第一個輸出b第二個輸出undefined 最後我們來看一種奇怪的呼叫方式 function A(a){ alert(this+","+a+","+'A'); } function B(b){ alert(this+","+b+","+'B'); } var C = A.call; A('a'); C.call(B,'a'); 大家看到這估計已經懵逼了吧,想不到還可以這麼呼叫吧 在這裡第一個alert輸出[object Window],a,A,結果正常,第二個alert輸出a,undefined,A,這時就有人會問了,為什麼a做了this指標而應該輸出a的地方卻輸出了undefined 我們先來看一下呼叫一次call方法輸出什麼 function A(a){ alert(this+","+a+","+'A'); } function B(b){ alert(this+","+b+","+'B'); } var C = A; A('a');//[object Window],a,A C.call(B,'a');// function B(b){alert(this+","+b+","+'B');},a,A 也就是說呼叫一次call方法是沒問題的而且將他的this指向了B 那麼在呼叫兩次call方法時A的this指標域指向了arguments的第一個引數,而後面的引數則是作為了arguments的引數。

 bind()

bind():這個方法會建立一個函式的例項,傳入引數與call方法相同
var name = 'global';
    function person () {
       this.name = 'hero';
    }
    // 輸出姓名、年齡和職業
    function print(age, job) {
        console.log(this.name, age, job);
    }
    var Person = new person();
    var printf = print.bind(Person);
    printf(18, '前端工程師');
    在這裡將print通過bind方法將this的指標改為了print,返回了一個函式,呼叫函式並傳入引數
    輸出hero 20 前端工程師

    但是對bind方法new會讓bind方法繫結的第一個引數消失

    function Person(name, age) {
        this.name = name;
        this.age = age;
    }

    var _Person = Person.bind(null, 'hanzichi');
    var p = new _Person(30); // Person {name: "hanzichi", age: 30}
    因為new方法導致bind第一個引數無效