1. 程式人生 > >call、apply、bind三者的用法和區別

call、apply、bind三者的用法和區別

1. call

call、apply、bind都是改變this指向的方法

  • fn.call

當前例項(函式fn)通過原型鏈的查詢機制,找到function.prototype上的call方法,function call(){[native code]}

  • fn.call()

把找到的call方法執行
call方法執行的時候,內部處理了一些事情
1.首先把要操作的函式中的this關鍵字變為call方法第一個傳遞的實參
2.把call方法第二個及之後的實參獲取到
3.把要操作的函式執行,並且把第二個以後傳遞進來的實參傳遞給函式

fn.call([this],[param]...)
  • call中的細節
  1. 非嚴格模式

如果不傳引數,或者第一個引數是nullnudefinedthis都指向window

    let fn = function(a,b){
        console.log(this,a,b);
    }
    let obj = {name:"obj"};
    fn.call(obj,1,2);    // this:obj    a:1         b:2
    fn.call(1,2);        // this:1      a:2         b:undefined
    fn.call();           // this:window a:undefined b:undefined
fn.call(null); // this=window a=undefined b=undefined fn.call(undefined); // this=window a=undefined b=undefined
  1. 嚴格模式

第一個引數是誰,this就指向誰,包括null和undefined,如果不傳引數this就是undefined

    "use strict"
    let fn = function(a,b){
        console.log(this,a,b);
    }
    let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2 fn.call(1,2); // this:1 a:2 b=undefined fn.call(); // this:undefined a:undefined b:undefined fn.call(null); // this:null a:undefined b:undefined fn.call(undefined); // this:undefined a:undefined b:undefined

2. apply

  • apply:和call基本上一致,唯一區別在於傳參方式

apply把需要傳遞給fn的引數放到一個數組(或者類陣列)中傳遞進去,雖然寫的是一個數組,但是也相當於給fn一個個的傳遞

fn.call(obj, 1, 2);
fn.apply(obj, [1, 2]);

3. bind

  • bind:語法和call一模一樣,區別在於立即執行還是等待執行,bind不相容IE6~8
fn.call(obj, 1, 2); // 改變fn中的this,並且把fn立即執行
fn.bind(obj, 1, 2); // 改變fn中的this,fn並不執行

this改變為obj了,但是繫結的時候立即執行,當觸發點選事件的時候執行的是fn的返回值undefined

document.onclick = fn.call(obj);

bind會把fn中的this預處理為obj,此時fn沒有執行,當點選的時候才會把fn執行

document.onclick = fn.bind(obj);