ES5和ES6的this

3,690 阅读2分钟

前言

整理一下javascript(包括ES3ES5ES6)中的this问题。

ECMAScript 3/5

这个版本的this很明确,只有以下五种情况:

全局

console.log(this); // this 等于 ECMAScript 在浏览器环境的 Global 对象,即 window

函数内

function foo() {
  console.log(this); // this 还是 window
}

方法调用

var obj = {
  name: 'alex',
  getName: function(){
    console.log(this.name);
  }
}
obj.getName(); // this 为 obj

var bar = obj.getName;
bar(); // 用这种方式调用,this 就指向了 window,因为这样调用时,函数的执行环境是全局的

构造函数

function Foo() {}
Foo.prototype.getName = function(){
  console.log(this.name);
}

var bar = new Foo();
bar.name = 'alex';
bar.getName(); // this 指向实例 bar

显示调用

applycall改变函数运行时的this指向

function foo(){
  console.log(this.name);
}

var applyObj = {
  name: 'alex'
}

var callObj = {
  name: 'f0rest'
}

foo.apply(applyObj); // alex
foo.call(callObj); // f0rest

ECMAScript 6

ES 6,我们大部分函数的写法都是使用箭头函数(arrow function),它的this不同于ES 5

箭头函数

// ES 5
var foo = function(options){ console.log('alex'); };
// ES 6
const foo = (options) => { console.log('alex'); };



// ES6 function to return a object
const foo = () => ({ name: 'f0rest' });

ES 6中的规则是,紧随箭头的{ 被解析为块的开始,而不是对象的开始,所以小括号包裹对象字面量是唯一一个你需要牢记的小窍门

this

箭头函数它没有自己的this值,它继承外围作用域的this

下面这个例子,thisundefined,因为ES 6是严格模式,严格模式下全局作用域的thisundefined

const foo = (options) => {
  console.log(this); // undefined
};

React中的实践

React组件中,注册事件有三种方式,目的是让事件函数内的this指向这个当前组件实例

我们用ES 6的语法来进行react应用开发

方法1

constructor方法中绑定

class App extends React.Component {
    constructor() {
        this.myEvent = this.myEvent.bind(this);
    }
    myEvent() {
      console.log(this);
    }
    render() {
        return (<div onClick={this.myEvent}>demo</div>);
    }
}

方法2

render方法中绑定,因为render方法已经为你绑定了this

class App extends React.Component {
    myEvent() {
      console.log(this);
    }
    render() {
        return (<div onClick={this.myEvent.bind(this)}>demo</div>);
    }
}

方法3

这里就是箭头函数,继承外围作用域的 this,即当前组件实例

class App extends React.Component {
    myEvent = () => {
      console.log(this);
    }
    render() {
        return (<div onClick={this.myEvent}>demo</div>);
    }
}

注: 如果你写的是通用组件,推荐第一种方式,这涉及原型的相关内容,暂且不表。

最后

谢谢阅读,如有谬误,恳请斧正。