You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
对于不是非常复杂的组件来说,这是一种非常不错的解决 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.
对于大多数开发者来说,JavaScript 的 this 关键字会造成诸多困扰。由于 JavaScript 不具备如 Java 等语言的严格类模型,因而除非是在处理回调,否则代码中的 this 指向并不清晰。
一般来说,对于部分运行中的代码(非回调)会通过 new 关键字和 Function.prototype 提供的一些方法,如 call/apply 等来绑定函数的上下文。
问题
在每个 class 中,React 使用 this 指向组件本身,这会给开发者造成一些困扰。如在 React 组件中,可能会经常看到类似如下的代码:
上述代码会造成 TypeError ,因为 this.setState 不是一个函数。抛出 TypeError 的原因是当 promise 的回调被调用时,内部的上下文已经改变了,this 指向了错误的对象。
那么,怎么正确绑定代码中的 this 呢?
选择
本文提供的 6 种方式中,有一些是比较老的技术,另一些是针对 React 的,还有一些可能浏览器也不支持,但还是值得探讨一下。
1、this 别名
这种方式就是在 React 组件的作用域顶端创建一个指向 this 的变量:
这种方式方便,易于理解,并能保证 this 会指向正确的上下文。
2、.bind(this)
这种方式是在函数运行时将 this 注入到回调中,使回调中的 this 能指向正确的上下文:
在 JavaScript 中,所有函数都有 bind 方法,其允许你为 this 指定特定值。一旦函数被绑定,上下文就不能被覆盖,也就意味着 this 会指向正确的上下文。
3、React Component Methods
当使用 React.createClass 来定义组件时,React 允许你随意在此组件的类中定义方法,而在方法中调用的 this 会自动绑定到组件自身:
对于不是非常复杂的组件来说,这是一种非常不错的解决 this 指向问题的方式。而事实上呢,如果在组件的方法中使用 .bind(this),React 会抛出一个警告:
但对于 ES2015 的类 来说,自动绑定并不适用。
4、箭头函数
ES2015 规范引入了箭头函数,使函数的定义更加简洁。箭头函数会隐式返回一个值,但更重要的是,它是在一个封闭的作用域中使用 this:
不管嵌套多少层,箭头函数中的 this 总能指向正确的上下文,因为函数体内的 this 指向的对象,就是定义时所在的对象,而不是使用时所在的对象。但缺点就是,由于箭头函数不能命名,因而在调试时,堆栈信息给的标签是 anonymous function。
如果你用 Babel 将 ES6 的代码转换成 ES5 的代码,就会发现两个有趣的现象:
在某些情况下,编译器能判断函数名是否被赋值给了某个变量
编译器使用 别名 来维护上下文
5、ES7 的绑定语法
在 ES7 中,有一个关于 bind 语法 的提议,提议将 :: 作为一个新的绑定操作符,该操作符会将左值和右值(一个函数)进行绑定。
以 map 的实现为例:
与 lodash 不同,我们不需要传递数据给 map 作为参数:
对下面的代码熟悉吗?
ES7 的绑定语法允许你像使用箭头函数一样使用 map:
在 React 中也是可以使用的:
6、方法传参指定
一些函数允许为 this 传递一个明确的值,保证其指向正确的上下文,例如 map 函数则将 this 作为最后一个参数:
虽然代码能运行,但这不是函数的一致实现。大部分函数并不接受 this 参数,所以最好还是采用上文中的其它方式来绑定 this 。
The text was updated successfully, but these errors were encountered: