HTML5中国

 找回密码
 立即注册

QQ登录

只需一步,快速开始

HTML5中国 首页 资源下载 文档下载 查看内容

React:ES6:ES7中的6种this绑定方法

2016-3-24 10:15| 发布者: admin| 查看: 1748| 评论: 0|来自: http://www.ido321.com/

摘要: 对多数开发者来说,JavaScript的this关键字会造成诸多困扰。由于JavaScript不具备如Java等语言的严格类模型,除非是在处理回调,否则代码中的this指向并不清晰。一般来说,对于部分运行中的代码(非回调)会通过new关 ...

  对于大多数开发者来说,JavaScript 的 this 关键字会造成诸多困扰。由于JavaScript 不具备如 Java 等语言的严格类模型,因而除非是在处理回调,否则代码中的 this 指向并不清晰。

 

  一般来说,对于部分运行中的代码(非回调)会通过 new 关键字和 Function.prototype 提供的一些方法,如call/apply 等来绑定函数的上下文。

 

 

  问题

 

  在每个 class 中,React 使用 this 指向组件本身,这会给开发者造成一些困扰。如在 React 组件中,可能会经常看到类似如下的代码:

this.setState({ loading: true });

fetch('/').then(function loaded() {
  this.setState({ loading: false });
});

  上述代码会造成 TypeError ,因为 this.setState 不是一个函数。抛出 TypeError 的原因是当 promise 的回调被调用时,内部的上下文已经改变了,this 指向了错误的对象。

 

  那么,怎么正确绑定代码中的 this 呢?

 

  选择

 

  本文提供的 6 种方式中,有一些是比较老的技术,另一些是针对 React 的,还有一些可能浏览器也不支持,但还是值得探讨一下。

 

  1、this 别名

  这种方式就是在 React 组件的作用域顶端创建一个指向 this 的变量:

var component = this;
component.setState({ loading: true });

fetch('/').then(function loaded() {
  component.setState({ loading: false });
});

  这种方式方便,易于理解,并能保证 this 会指向正确的上下文。

 

  2、.bind(this)

  这种方式是在函数运行时将 this 注入到回调中,使回调中的 this 能指向正确的上下文:

this.setState({ loading: true });

fetch('/').then(function loaded() {
  this.setState({ loading: false });
}.bind(this));

  在 JavaScript 中,所有函数都有 bind 方法,其允许你为 this 指定特定值。一旦函数被绑定,上下文就不能被覆盖,也就意味着 this 会指向正确的上下文。

 

  3、React Component Methods

  当使用 React.createClass 来定义组件时,React 允许你随意在此组件的类中定义方法,而在方法中调用的 this 会自动绑定到组件自身:

React.createClass({
  componentWillMount: function() {
    this.setState({ loading: true });

    fetch('/').then(this.loaded);
  },
  loaded: function loaded() {
    this.setState({ loading: false });
  }
});

 

  对于不是非常复杂的组件来说,这是一种非常不错的解决 this 指向问题的方式。而事实上呢,如果在组件的方法中使用.bind(this),React 会抛出一个警告:

bind(): You are binding a component method to the component. React does this for you automatically in a high-performance way, so you can safely remove this call.

  但对于 ES2015 的类来说,自动绑定并不适用。

 

  4、箭头函数

  ES2015 规范引入了箭头函数,使函数的定义更加简洁。箭头函数会隐式返回一个值,但更重要的是,它是在一个封闭的作用域中使用 this:

this.setState({ loading: true });

fetch('/').then(() => {
  this.setState({ loading: false });
});

  不管嵌套多少层,箭头函数中的 this 总能指向正确的上下文,因为函数体内的 this 指向的对象,就是定义时所在的对象,而不是使用时所在的对象。但缺点就是,由于箭头函数不能命名,因而在调试时,堆栈信息给的标签是anonymous function。

 

  如果你用 Babel 将 ES6 的代码转换成 ES5 的代码,就会发现两个有趣的现象:

  •   在某些情况下,编译器能判断函数名是否被赋值给了某个变量
  •   编译器使用别名来维护上下文
const loaded = () => {
  this.setState({ loading: false });
};

// will be compiled to

var _this = this;
var loaded = function loaded() {
  _this.setState({ loading: false });
};


  5、ES7 的绑定语法

  在 ES7 中,有一个关于 bind 语法 的提议,提议将 :: 作为一个新的绑定操作符,该操作符会将左值和右值(一个函数)进行绑定。

  以 map 的实现为例:

function map(f) {
  var mapped = new Array(this.length);

  for(var i = 0; i < this.length; i++) {
    mapped[i] = f(this[i], i);  
  }

  return mapped;
}

  与 lodash 不同,我们不需要传递数据给 map 作为参数:

[1, 2, 3]::map(x => x * 2)
// [2, 4, 6]

 

  对下面的代码熟悉吗?

[].map.call(someNodeList, myFn);
// or
Array.from(someNodeList).map(myFn);


  ES7 的绑定语法允许你像使用箭头函数一样使用 map:

someNodeList::map(myFn);


  在React 中也是可以使用的:

this.setState({ loading: true });

fetch('/').then(this::() => {
  this.setState({ loading: false });
});


  6、方法传参指定

  一些函数允许为 this 传递一个明确的值,保证其指向正确的上下文,例如 map 函数则将 this 作为最后一个参数:

items.map(function(x) {
  return x;
}, this);

  虽然代码能运行,但这不是函数的一致实现。大部分函数并不接受 this 参数,所以最好还是采用上文中的其它方式来绑定this 。

 

  原文: 6 Ways to Bind JavaScript‘s this Keyword in React, ES6 & ES7

  译文:http://www.html5cn.org/portal.php?mod=portalcp&ac=article&catid=51

      译者:@会飞的Pikachu


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论

HTML5中国微信

小黑屋|关于我们|HTML5论坛|友情链接|手机版|HTML5中国 ( 京ICP备11006447号 京公网安备:11010802018489号  

GMT+8, 2017-1-18 05:15

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

返回顶部