# this 是什么
this 是执行当前函数的对象 (The object that is executing the current function)
- 以对象方法的形式调用 this 就是调用方法的对象
- 以普通函数的形式调用,this 在浏览器中是 window 对象,在 node 中是 global 对象 (实际也是 window /global 对象的方法)
- 以构造函数的形式调用,this 是构造函数创建返回的对象
- 回调函数也是以普通函数的形式调用
# 对象方法和普通函数中的 this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const video = { title: "a", play() { console.log(this); }, };
video.stop = function () { console.log(this); };
video.stop(); video.play(); stop = video.stop; stop();
function playVideo() { console.log(this); }
playVideo();
|
# 构造函数中的 this
构造函数创建对象的过程 const v = new Video("b");
- 创建空的对象 {}
- this 指向空的对象 {}, 为 this 即 {} 设定属性
- 返回 this
1 2 3 4 5 6
| function Video(title) { this.title = title; console.log(this); }
const v = new Video("b");
|
# 回调函数中的 this
如下 forEach 回调函数不是 video 的方法,是由 global/window 调用的普通函数,global 和 window 中没有定义 title,所以值是 undefined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const video = { title: "a", tags: ["a", "b", "c"], showTags() { this.tags.forEach(function (tag) { console.log(this.title, tag); }); }, };
video.showTags();
|
# 回调函数 this 绑定问题解决方式
# 函数参数指定 this
有些函数参数可以指定 this, 例如 forEach 第二个参数可以指定 this
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const video = { title: "a", tags: ["a", "b", "c"], showTags() { this.tags.forEach(function (tag) { console.log(this.title, tag); }, this); }, };
video.showTags();
|
# 中间变量保存 this
使用变量存储容器对象中的 this, 如下使用 self 存储对象方法 showTags 中的 this, 在回调中使用 self 而不是 this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const video = { title: "a", tags: ["a", "b", "c"], showTags() { const self = this; this.tags.forEach(function (tag) { console.log(self.title, tag); }); }, };
video.showTags();
|
# bind/call/apply
使用 bind 函数返回的新函数不论以何种方式调用 this 都不会变是 bind 时指定的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| function playVideo(a, b) { console.log(this, a, b); } playVideo.call({ name: "Babb" }, 1, 2); playVideo.apply({ name: "Babb" }, [1, 2]); const fn = playVideo.bind({ name: "Babb" }); fn(1, 2);
const video = { title: "a", tags: ["a", "b", "c"], showTags() { this.tags.forEach( function (tag) { console.log(this.title, tag); }.bind(this) ); }, };
video.showTags();
|
# arrow function
箭头函数会从容器方法中继承 this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const video = { title: "a", tags: ["a", "b", "c"], showTags() { this.tags.forEach((tag) => { console.log(this.title, tag); }); }, };
video.showTags();
|