this的指向和用法

this的指向是javascript种一个老生常谈的问题,今天我以一个项目实践来谈谈this在工作中的使用。

基础知识

我们知道,this对象是在运行时基于函数的执行环境绑定的:在全局作用域中this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。

工作中遇到的问题

下面我们在这样的一个环境里面来判断this的指向

class Page {
  constructor() {
    Hybrid('customNavBarRightBtn').customNavBarRightBtn({
      //默认隐藏右上角分享按钮
      hidden: true
    })
    this.$activity = $('#activity')

    this.bindEvents()

    getData()
      .then(res => {
        this.res = res
        this.albums = [res.albums.slice(0, 3), res.albums.slice(3, 6)]
        this.res.albums = this.albums[0]
        this.$activity.html(tpl.render(this.res))
      })
      .catch(err => {
        popup.note(err.message || err.err_msg || JSON.stringify(err))
      })
  }
}
new Page()

class是es6中的一个语法糖,关于它的详细介绍请参看阮一峰《ES6标准入门》

在上面这段代码中,this全部都指向Page的实例,我之所以要用this来储存变量是为了下面一段代码

class Page {
  constructor() {
    ...
    ...
    ...
  }
  bindEvents() {
    let _this = this
    this.$activity.on('click', '.changMusic', function() {
      if (_this.res.albums === _this.albums[0]) {
        _this.res.albums = _this.albums[1]
      } else {
        _this.res.albums = _this.albums[0]
      }
      _this.$activity.html(tpl.render(_this.res))
    })
  }
}
new Page()

这里我使用_this来江this保存起来,是因为在点击事件的作用域里,this是指向绑定的点击的div的,但是我希望this指向class的实例。这里除了将this存起来以外,还有其他的方法。这里我介绍两种:

  • 使用ES6箭头函数。我们知道,在ES5中,this指向的是执行时的作用域,而在ES6this指向定义时的作用域。所以使用箭头函数,thiss的作用域就变成class的实例了。但是这样做有一个问题,如果我们想使用$(this)来对点击事件进行操作,那就不行了,因为在箭头函数中无法使用call()或apply()方法。为什么不能使用呢?因为箭头函数里根本没有自己的this,导致内部的this就是外部代码块的this。因为它没有this,所以他也不能作为构造函数。
  • 使用call或apply()改变this指向。

this在什么时候使用

其实如果我们定义的一个变量,只需要在某一个函数中使用,是不需要用到this的。但是有时候我们希望函数内的变量在函数外也还能用,就可以用this了。特别是在使用es6的class的时候,我们可以要在整个class中用到的变量放在constructor中,这样在class下面的函数中都可以对变量进行操作了。

posted @ 2018-01-25 09:56  叫我小红依吧  阅读(632)  评论(0编辑  收藏  举报