鍍金池/ 問答/Java  HTML/ js回調(diào)this問題

js回調(diào)this問題

兩個(gè)調(diào)用 第二次進(jìn)行回調(diào)的時(shí)候 this 標(biāo)記1和 this 標(biāo)記2值不一樣
這是為何?

 function a (val, callback) {
      callback.call(a,val,callback)
    }
    a(1,function b (val ,callback) {
        console.log(this, '標(biāo)記1')
        console.log(val)
        console.log(callback)
        callback(2,function c(val, callback){
        console.log(this)
        console.log(val)
        console.log(callback)
        console.log('over')
      })
    })
    console.log('-----分割線-------')
    a(1,function b () {
        console.log(this, '標(biāo)記2')
        console.log(arguments[0])
        console.log(arguments[1])
        arguments[1](2,function c(){
        console.log(this)
        console.log(arguments[0])
        console.log(arguments[1])
        console.log('over')
      })
    })

clipboard.png

回答
編輯回答
舊時(shí)光

第一步,先看函數(shù)a定義

clipboard.png

觀察callback,上圖中一共有三個(gè)callback,分別是

  1. 函數(shù)a的參數(shù)中的callback
  2. 綁定在a上執(zhí)行的callback, 它執(zhí)行時(shí)對(duì)應(yīng)的this是函數(shù)a
  3. 2號(hào)callback執(zhí)行時(shí)的參數(shù)中的callback,3號(hào)callback執(zhí)行時(shí)并沒有明確指定this綁定誰(shuí),在執(zhí)行時(shí)確定

第二步,簡(jiǎn)化你的試驗(yàn)代碼,突出this

function a(val, callback) {
    callback.call(a,val,callback);
}


a(1, function b(val ,callback) {
    console.log(this, '標(biāo)記10的this');
    callback(2, function c(val, callback){
        console.log(this, '標(biāo)記11的this');
    });
});

console.log('-----分割線-------');

a(1, function b() {
    console.log(this, '標(biāo)記20的this')
    arguments[1](2, function c(){
        console.log(this, '標(biāo)記21的this');
    });
});

第三步, 分析分割線上半部分執(zhí)行結(jié)果

a(1, function b(val ,callback) {
    console.log(this, '標(biāo)記10的this');
    callback(2, function c(val, callback){
        console.log(this, '標(biāo)記11的this');
    });
});
//輸出: a 標(biāo)記10的this
//輸出: window 標(biāo)記10的this
//輸出: window 標(biāo)記11的this

進(jìn)一步簡(jiǎn)化,上面代碼實(shí)際是 a(1, b), 結(jié)合第一步的圖,

  1. b第一次執(zhí)行時(shí),對(duì)應(yīng)第一步圖中2號(hào)callback,

    1. 第一行開始執(zhí)行:輸出是 "a 標(biāo)記10的this“
    2. 第二行開始執(zhí)行:callback對(duì)應(yīng)第一步圖中3號(hào)callback,在此代指函數(shù)b,故等價(jià)于 b(2,c), b被第二次執(zhí)行。
  2. b第二次執(zhí)行時(shí)b(2,c),并未綁定任何對(duì)象,默認(rèn)在window上執(zhí)行,故this是window

    1. 第一行開始執(zhí)行:輸出 "window 標(biāo)記10的this"
    2. 第二行開始執(zhí)行:等價(jià)于 c(2,c)
    3. 第三行開始執(zhí)行:c并未綁定任何對(duì)象,默認(rèn)綁定在window上。 輸出 ”window 標(biāo)記11的this“

第四步, 分析分割線下半部分執(zhí)行結(jié)果

a(1, function b() {
    console.log(this, '標(biāo)記20的this')
    arguments[1](2, function c(){
        console.log(this, '標(biāo)記21的this');
    });
});
//輸出: a 標(biāo)記20的this
//輸出: arguments 標(biāo)記20的this
//輸出: arguments 標(biāo)記21的this

進(jìn)一步簡(jiǎn)化,上面代碼實(shí)際是 a(1, b), 結(jié)合第一步的圖,

  1. b第一次執(zhí)行時(shí),對(duì)應(yīng)第一步圖中2號(hào)callback,

    1. 第一行開始執(zhí)行:輸出是 "a 標(biāo)記20的this“
    2. 第二行開始執(zhí)行:arguments[1]對(duì)應(yīng)第一步圖中3號(hào)callback,在此代指函數(shù)b,特別注意等價(jià)于綁定在arguments上執(zhí)行b(2,c), b被第二次執(zhí)行,為了好理解,你就理解為 arguments.b(2,c);
    3. 插播一段,數(shù)組內(nèi)函數(shù)執(zhí)行后,這個(gè)函數(shù)中的this默認(rèn)指向數(shù)組:
    var arr = [function(){console.log(this)}];
    arr[0]();  // 輸出的this的是 arr
  2. b第二次執(zhí)行時(shí)arguments.b(2,c) (注意,只是為了好理解,實(shí)際是arguments[1]代b執(zhí)行。),綁定在arguments對(duì)象上執(zhí)行b,故this是arguments

    1. 第一行開始執(zhí)行:輸出 "arguments 標(biāo)記20的this"
    2. 第二行開始執(zhí)行:等價(jià)于 arguments.c(2,c) (注意,只是為了好理解,實(shí)際是arguments[1]代c執(zhí)行。)
    3. 第三行開始執(zhí)行:c也綁定在arguments上。 輸出 ”arguments 標(biāo)記21的this“
2018年7月29日 18:48
編輯回答
玄鳥

抱歉看不下去, 只看了前面兩位的答案,大概就是這樣了。

2017年1月24日 18:32
編輯回答
愿如初

翻譯一下你的代碼,說(shuō)實(shí)話,你這命名不改一下真是誰(shuí)都看不懂。

 function a(val, aCallback) {
     aCallback.call(a, val, aCallback)
 }

 a(1, function b(val, bCallback) { //b.call(a,1,callback) ->  b(1,a.callback) -> bCallback = function b(val,bCallback) -> this指向a
     console.log( this, '標(biāo)記1')

     bCallback(2, function c(val, cCallback) { // b() -> bCallback = function c -> bCallback是個(gè)function 采用默認(rèn)綁定 this指向window
         console.log('over 1')
     })
 })

 a(1, function b() { //b.call(a,1,callback) ->  b(1,a.callback) -> bCallback = function b(val,bCallback) -> this指向a
     console.log( this, '標(biāo)記2')

     arguments[1](2, function c() { // b() -> bCallback = function c ->  由于arguments是個(gè)對(duì)象 采用隱式綁定 this指向arguments
         console.log('over 2')
     })
 })
2017年11月19日 10:09