JavaScript的this丢了怎么办?

发布时间 2023-05-27 05:11:30作者: 布衣梦蝶1978

JavaScript的this丢了怎么办?

bind方法

先来看一个常见的问题,以下示例中:

this.firstName 没有输出我们期望的 “John”,而显示了 undefined

let user={
        firstName:"John",
        sayHi(){
            console.log(`Hello,${this.firstName}!`);
        }
    } ;
    setTimeout(user.sayHi.bind(user),1000)

这是因为 setTimeout 获取到了函数 user.sayHi,但它和对象分离开了,一旦方法被传递到与对象分开的某个地方 —— this 就丢失了。

在浏览器中, setTimeout 为函数调用设定了 this=window。所以对于 this.firstName,实时上变成了 window.firstName,很明显这是不存在的,所以结果变成了undefined

函数提供了一个内建方法 bind,它可以绑定 this

基本语法:let boundFunc = func.bind(context);

现在我们把上面的例子,加上bind方法在来试一下:

user.sayHi.bind(user)

可以看到输出结果正常,这句话的意思其实就是将当前的将 this 绑定到 user,

这样this.firstName就可以获取到正确的值了。

偏函数(Partial functions)

上面说到了绑定 this,事实上不仅可以绑定 this,还可以绑定参数(arguments)。

bind` 的完整语法:`let bound = func.bind(context, [arg1], [arg2], ...);

它允许将上下文绑定为 this,以及绑定函数的起始参数。

?示例:mul(a, b)是一个乘法函数

function mul(a, b) {
  return a * b;
}

现在我们想要在这个函数的基础上,创建一个double 函数,该怎么做呢?

你如果使用bind函数,很简单就可以实现了。

// 2倍函数
let double = mul.bind(null, 2);

function mul(a,b,c){
        return a*b+c
    }
    let double=mul.bind(null,2)
    console.log(double(3,8))

分析

  • mul.bind(null, 2) 的调用创建了一个新函数 double
  • 它将调用传递到 mul,将 null 绑定为上下文
  • 2 绑定为第一个参数,即 a = 2
  • 而剩余参数(arguments)均被“原样”传递,即double(3),里面的3被原因传递给了b

从而非常简单的实现了,2倍函数,如果要实现3倍函数,直接传递3就可以了

let triple = mul.bind(null, 3);
注意:这里我们实际上没有用到 this。但是 bind 需要它,所以我们必须传入 null 之类的东西。

像上面这种,通过绑定先有函数的一些参数来创建一个新函数。叫做偏函数应用程序(partial function application)

为什么要创建偏函数?

首先:我们可以创建一个具有可读性高的名字(doubletriple)的独立函数。我们可以使用它,并且不必每次都提供一个参数,因为参数是被绑定了的。

其次:当我们有一个非常通用的函数,并希望有一个通用型更低的该函数的变体时,偏函数会非常有用。

什么时候会用到偏函数?

当我们不想一遍又一遍地重复相同的参数时,偏函数非常有用。就像我们有一个 send(from, to) 函数,并且对于我们的任务来说,from 应该总是一样的,那么我们就可以搞一个偏函数并使用它。