对绝大多数开发人员而言,JavaScript 的 this URL会导致众多所苦。虽然 JavaScript 不具备如 Java 等词汇的严苛类数学模型,因此假如是在处置反弹,不然标识符中的 this 对准并不明晰。
一般而言,对部份运转中的标识符(非反弹)会透过 new URL和 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 tovar 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);// orArray.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 。