4

两个调用 第二次进行回调的时候 this 标记1和 this 标记2值不一样
这是为何?

 function a (val, callback) {
      callback.call(a,val,callback)
    }
    a(1,function b (val ,callback) {
        console.log(this, '标记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, '标记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

2018-08-22 提问
3 个回答
3

已采纳

第一步,先看函数a定义

clipboard.png

观察callback,上图中一共有三个callback,分别是

  1. 函数a的参数中的callback
  2. 绑定在a上执行的callback, 它执行时对应的this是函数a
  3. 2号callback执行时的参数中的callback,3号callback执行时并没有明确指定this绑定谁,在执行时确定

第二步,简化你的试验代码,突出this

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


a(1, function b(val ,callback) {
    console.log(this, '标记10的this');
    callback(2, function c(val, callback){
        console.log(this, '标记11的this');
    });
});

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

a(1, function b() {
    console.log(this, '标记20的this')
    arguments[1](2, function c(){
        console.log(this, '标记21的this');
    });
});

第三步, 分析分割线上半部分执行结果

a(1, function b(val ,callback) {
    console.log(this, '标记10的this');
    callback(2, function c(val, callback){
        console.log(this, '标记11的this');
    });
});
//输出: a 标记10的this
//输出: window 标记10的this
//输出: window 标记11的this

进一步简化,上面代码实际是 a(1, b), 结合第一步的图,

  1. b第一次执行时,对应第一步图中2号callback,

    1. 第一行开始执行:输出是 "a 标记10的this“
    2. 第二行开始执行:callback对应第一步图中3号callback,在此代指函数b,故等价于 b(2,c), b被第二次执行。
  2. b第二次执行时b(2,c),并未绑定任何对象,默认在window上执行,故this是window

    1. 第一行开始执行:输出 "window 标记10的this"
    2. 第二行开始执行:等价于 c(2,c)
    3. 第三行开始执行:c并未绑定任何对象,默认绑定在window上。 输出 ”window 标记11的this“

第四步, 分析分割线下半部分执行结果

a(1, function b() {
    console.log(this, '标记20的this')
    arguments[1](2, function c(){
        console.log(this, '标记21的this');
    });
});
//输出: a 标记20的this
//输出: arguments 标记20的this
//输出: arguments 标记21的this

进一步简化,上面代码实际是 a(1, b), 结合第一步的图,

  1. b第一次执行时,对应第一步图中2号callback,

    1. 第一行开始执行:输出是 "a 标记20的this“
    2. 第二行开始执行:arguments[1]对应第一步图中3号callback,在此代指函数b,特别注意等价于绑定在arguments上执行b(2,c), b被第二次执行,为了好理解,你就理解为 arguments.b(2,c);
    3. 插播一段,数组内函数执行后,这个函数中的this默认指向数组:
    var arr = [function(){console.log(this)}];
    arr[0]();  // 输出的this的是 arr
  2. b第二次执行时arguments.b(2,c) (注意,只是为了好理解,实际是arguments[1]代b执行。),绑定在arguments对象上执行b,故this是arguments

    1. 第一行开始执行:输出 "arguments 标记20的this"
    2. 第二行开始执行:等价于 arguments.c(2,c) (注意,只是为了好理解,实际是arguments[1]代c执行。)
    3. 第三行开始执行:c也绑定在arguments上。 输出 ”arguments 标记21的this“
0

翻译一下你的代码,说实话,你这命名不改一下真是谁都看不懂。

 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, '标记1')

     bCallback(2, function c(val, cCallback) { // b() -> bCallback = function c -> bCallback是个function 采用默认绑定 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, '标记2')

     arguments[1](2, function c() { // b() -> bCallback = function c ->  由于arguments是个对象 采用隐式绑定 this指向arguments
         console.log('over 2')
     })
 })
0

抱歉看不下去, 只看了前面两位的答案,大概就是这样了。

该答案已被忽略,原因:无意义的内容 - 赞、顶、同问等毫无意义的内容

撰写答案

推广链接