为什么不能使用 lambda 构造将方法订阅到数据表的点击事件?

Why cannot subsribe a method to a datatable's click event with the lambda construct?

我在 angular 5 中使用数据表 (datatables.net),我正在订阅一种方法来响应 tr 上的点击事件,如下所示:

const tableRef = this.table;    // bound datatable and router to scope 
const routerRef = this.router;  // so I can use them inside the callBack
this.table.on('click', 'tbody tr', function (e) {
    const $tr = $(this).closest('tr');
    const data = tableRef.row($tr).data();
    if (data !== undefined) {
        routerRef.navigateByUrl(`/some/url/details/${data.id}`);
    }
});

它几乎与 datatables.net 上的样本相同 网站。事情是这样的,后来我决定像下面这样更改我的代码:

this.table.on('click', 'tbody  tr', this.rowClicked(this.table, this.router));

//...

private rowClicked(table, router: Router) {
    return (e) => {
        const $tr = $(this).closest('tr');
        const data = table.row($tr).data();
        if (data !== undefined) {
            router.navigateByUrl('/some/url/details/`${data.id}`');
        }
    }
}

而且...令我惊讶的是它什么也没做,连眨眼都没有!然后我继续 并将 console.log('row clicked'); 放入 lambda 中(如果可以这样命名, 我真的是 typescript 的新手),每当我点击 trdata 时它就会打印出来 总是 undefined。我什至为 $("#my-datatable-id").DataTable() 更改了 table 变量 仍然没有运气。几分钟后,我决定 git diff 文件并意识到唯一的 不同之处在于回调的构造方式(使用关键字 function)所以我这样做并将 lambda 更改为:

private rowClicked(table, router: Router) {
    return function (e) {
        // same as before
    }
}

猜猜看,成功了!它像魅力一样获取了 tr 的数据。那么,任何人都可以 向我解释为什么在使用 lambda 时我无法从行中获取 data 和 当我使用 function 构造时。提前致谢!

我不知道 Angular,但我认为 this.table.on 正在将自定义 this 上下文传递给 $(this) 所必需的回调你打算。当您使用箭头函数时,this.table.on 传递的上下文将被忽略,而 this 会引用调用 rowClicked 的对象,因此您会得到不同的结果。

如果我没记错的话,是因为Javascript Closuresthis左右。

这两个不产生相同的this:

this.table.on('click', 'tbody tr', function (e) {
  // "this" is what you think it is
});

this.table.on('click', 'tbody  tr', this.rowClicked(this.table, this.router));

private rowClicked(table, router: Router) {
  // "this" should be window
  return (e) => {
    const $tr = $(this).closest('tr');
    const data = table.row($tr).data();
    if (data !== undefined) {
        router.navigateByUrl('/some/url/details/`${data.id}`');
    }
  }
}

您应该可以简单地修复它:

this.table.on('click', 'tbody  tr', () => this.rowClicked(this.table, this.router));

this.table.on('click', 'tbody  tr', () => { return this.rowClicked(this.table, this.router); });

因为上面创建了...好吧,我会调用,这个上的一个匿名函数然后内部调用rowClicked的范围是正确的(不是window).