this指向

标准函数:this 指向调用该函数的上下文对象。
箭头函数:this 引用的是定义箭头函数的上下文。

示例(标准函数):

  1. var a = "window.a";
  2. var obj = {
  3. a: "window.obj.a",
  4. fn() {
  5. console.log(this.a);
  6. }
  7. };
  8. obj.fn(); // window.obj.a

示例(箭头函数):

  1. var a = "window.a";
  2. var obj = {
  3. a: "window.obj.a",
  4. fn: () => {
  5. console.log(this.a);
  6. }
  7. };
  8. obj.fn(); // window.a

注意:
全局上下文中,this 指向的是 window。但在 严格模式 下,全局上下文中 this 指向的会是 undefined

使用 call、apply、bind 替换 this 指向

我们先提供一个需求:

  1. var hong = {
  2. name: "小红",
  3. intro(age, from) {
  4. console.log("姓名:", this.name);
  5. console.log("年龄:", age);
  6. console.log("来自:", from);
  7. }
  8. };
  9. var wang = {
  10. name: "老王"
  11. };
  12. hong.intro(15, "北京"); // 姓名:小红 年龄:15 来自:北京

来自上海的30岁的老王,也想做个自我介绍。但是他并没有 intro 方法。因此他只能找小红借该方法。把其中的 this 指向自己,通过传参得出年龄和来源地区。

这时候我们就需要用到 call、apply、bind 了。其中 call、apply 比较相像,bind比较特殊。

call

使用:fn.call(obj, 参数1, 参数2, ..., 参数n)

参数 描述
obj 要调用该函数的上下文对象
参数1 fn 函数本身需要的第 1 个参数
参数2 fn 函数本身需要的第 2 个参数
参数n fn 函数本身需要的第 n 个参数

使用 call 帮助老王:

  1. hong.intro.call(wang, 30, '上海') // 姓名:老王 年龄:30 来自:上海

apply

使用:fn.call(obj, [参数1, 参数2, ..., 参数n])

参数 描述
obj 要调用 fn 函数的上下文对象
[参数1, 参数2, …, 参数n] 以数组的形式,传入 fn 函数本身所需要的所有参数

使用 apply 帮助老王:

  1. hong.intro.apply(wang, [30, '上海']) // 姓名:老王 年龄:30 来自:上海

bind

bind 跟前两个方法有些不同。它不立即执行函数,而是返回一个已绑定好新 this 的函数,后续可多次调用。

使用:var newFn = fn.bind(obj, 参数1, 参数2, ..., 参数n)

参数 描述
obj 要调用 fn 函数的上下文对象
参数1 fn 函数需要的第 1 个参数(作为默认值,且后续无法覆盖),非必填。
参数x fn 函数需要的第 x 个参数(作为默认值,且后续无法覆盖),非必填。
返回值 描述
newFn 返回一个原函数的拷贝,并拥有指定的 this 和 初始参数

它接收参数的形式跟 call 比较相似,但功能上有很大的区别,bind可以有两种用法:

  1. 仅传入第一个参数(要调用fn函数的上下文对象): ```javascript var myIntro = hong.intro.bind(wang);

myIntro(30, ‘上海’); // 姓名:老王 年龄:30 来自:上海 myIntro(40, ‘深圳’); // 姓名:老王 年龄:40 来自:深圳

  1. 只传入第一个参数时,可以在后续调用新函数时传入原函数所需要的参数。
  2. 2. bind 时就传入原函数需要的参数:
  3. ```javascript
  4. var myIntro = hong.intro.bind(wang, 30, '上海');
  5. myIntro(); // 姓名:老王 年龄:30 来自:上海
  6. myIntro(40, '深圳'); // 姓名:老王 年龄:30 来自:上海

若在使用 bind 时传入了 fn 函数本身所需的参数。那么后面调用时无需再传入原函数所需的参数。且后续调用时无法覆盖这些参数。