vue中,什么时候要把this赋值给that,为什么要这么做?

Neoo1984
  • 53

如题,this指向的是当前运行的环境,在一个函数哪let that = this是不是为了改变this的指向,让this指向当前函数这个运行环境对象呢?
在vue中,为什么调用data里定义的值,需要用this?因为当前的运行环境是对象吗,是当前的这个.vue文件吗,它是个什么对象?
不知道是哪个大聪明踩了一下

回复
阅读 2.2k
6 个回答

JS 中以 function 关键字声明的函数,其 this 所指向的对象在调用时才能确定,而内层函数又不会自动继承外层函数的 this
有时候我们需要在内层函数中使用外层函数的 this,这时候可以在外层定义 var that = this,然后在内层访问这个 that 就行了,这里相当于给外层的 this 起了个别名,而不是“改变this的指向”。但是现在既然有了箭头函数,就没必要用这么麻烦的方法了。
Vue 的各个方法中访问的 this 指的是 Vue 实例,这个 thisVue 初始化的时候帮你绑定好的。

首先从执行上下文的角度解释下const that = this
我们知道执行上下文包含:词法环境、变量环境、this、作用域链(outer)等,this 是和执行上下文绑定的。将this 赋值 给 一个变量/常量,目的将当前this绑定到当前执行环境中的词法/变量环境中。

什么时候需要这样操作?
嵌套函数中的 this 与你预期的不一致。

Vue中的this指向的是什么?
当前组件的实例。

this 不是指 .vue 文件,.vue 文件只是要通过 complier 处理的单文件组件,一种形式而已。 你或许经常在 vue 文档中看到 vm —— 组件实例。

如果你使用箭头函数,那么几乎不用 let that = this。推荐学习 JavaScript this 的指向问题。

先说结论吧:当在一个函数里定义另一个函数的回调函数时,就需要把 this 赋值给 that
来看个例子吧:

const user = {
  state: {
    firstName: '罗',
    lastName: '曼'
  },
  getFullName() {
    let firstName = this.state.firstName;
    let lastName = this.foo(function () {
      // console.log(this);
      return this.state.lastName;
    })
    console.log(`hello, ${firstName} ${lastName}`);
  },
  foo(cb) {
    return cb();
  },
}
// 获取fullName
user.getFullName();

如果直接这样使用,会发生什么呢?
显然,控制台会报错,如下

Uncaught TypeError: Cannot read property 'lastName' of undefined

根据报错,我们可以定位到foo的回调函数里
也就是这段

function () {
  // console.log(this);
  return this.state.lastName;
}

这个函数里的this是什么呢?可以打印出来看一下

function () {
  console.log(this); // 在非严格模式下,它是 window。
  return this.state.lastName;
}

显然错误的原因是回调函数内的this丢失了, 指向了window。函数试图去访问widwon.state.lastName,当然就会报错啦。有关this指向问题,这里就不再赘述了。

解决方案:

  1. 在进入回调函数前,保存当前this, 代码可以改成下面的形式
const user = {
  state: {
    firstName: '罗',
    lastName: '曼'
  },
  getFullName() {
    let firstName = this.state.firstName;

    let that = this; // 保存当前this
    
    let lastName = this.foo(function () {
      console.log(that); // user
      return that.state.lastName; // 使用已保存的 this 去访问
    })
    console.log(`hello, ${firstName} ${lastName}`);
  },
  foo(cb) {
    return cb();
  },
}
// hello, 罗 曼
user.getFullName();
  1. 使用箭头函数, 有关箭头函数的指向,也不做过多说明了
const user = {
  state: {
    firstName: '罗',
    lastName: '曼'
  },
  getFullName() {
    let firstName = this.state.firstName;
    // 不再需要 let that = this 了, 太不优雅了!

    let lastName = this.foo(() => {
      console.log(this);
      return this.state.lastName;
    })
    console.log(`hello, ${firstName} ${lastName}`);
  },
  foo(cb) {
    return cb();
  },
}
// hello, 罗 曼
user.getFullName();

这样做一般是为了保留this指向,有时候在一些内层函数内,他的this指向并不是当前的Vue实例,所以要定义一个值保存一下this,在需要访问调用Vue实例的时候使用

这只能说根据逻辑需要~

宣传栏