bind()
- ES5 引入了
Function.prototype.bind。 bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。- 也就是说,调用
f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数(someObject)上,无论这个函数是如何被调用的。bind绑定的参数只生效一次。
注意
- 函数使用bind()返回的还是一个函数,而
call()/apply()则是直接调用函数。 - 使用函数声明的方式创建的函数不能使用
bind(),只有使用函数表达式的方式创建的函数才能使用。 call()/apply()/bind()都是使用第一个参数改变this的指向。bind()与call()/apply()的传参方法有所不同。
bind()与apply()、call()的共同点
- 在JS中,这三者都是用来改变函数的this对象的指向的。
- 都是用来改变函数的this对象的指向的。
- 第一个参数都是this要指向的对象。
- 都可以利用后续参数传参。
- 注意:call, apply, bind 都不能改变箭头函数中的this指向
- 因为箭头函数的this只和定义时的作用域this有关,和调用者/调用环境无关,也永远不会改变
bind()与apply()、call()使用上的区别
无参数情况
1 | var xw = { |
- 用xw的say方法来显示xh的数据的几种方法:
xw.say.call(xh);xw.say.apply(xh);xw.say.bind(xh)();- 如果直接写
xw.say.bind(xh)不会有任何结果,call()和apply()都是对函数的直接调用,而**bind()返回的仍然是一个函数,因此后面还需要()来进行调用才可以**。
- 如果直接写
传参情况
1 | var xw = { |
- 可以看到say方法多了两个参数,我们通过4种方法进行传参:
xw.say.call(xh,"实验小学","六年级");xw.say.apply(xh,["实验小学","六年级"]);xw.say.bind(xh,"实验小学","六年级")();xw.say.bind(xh)("实验小学","六年级");
- 由于
bind()返回的仍然是一个函数,所以我们还可以在调用的时候再进行传参。
react事件绑定函数与bind(this)
在react中,常看到:
1 | export default class App extends Component { |
- **事件绑定处理函数(
onPress={this.foo})时,foo方法内部的this的指向就会丢失(此时在foo函数内部打印this得到的是undefined)**。这就会出现外部的foo方法内部的this会丢失指向。 - 为了解决这个问题,我们在实例化对象的时候就需要在构造函数中绑定
this(this.foo = this.foo.bind(this);),使得无论事件处理函数如何传递,它的this的指向都是固定的,固定指向我们所实例化的对象(App组件)。- 虽然在render函数中
<Button onPress={this.foo.bind(this)}/>效果一样,但比较消耗性能,不推荐。 - 具体应用可参考笔记“React.js基础精讲(1)”中的“React中的响应式设计思想和事件绑定”
- 虽然在render函数中
父组件传递函数给子组件也需绑定
- 注意:如父组件要传递函数给子组件,则需在父组件构造函数中使用
bind绑定该函数this指向- 原因:绑定
this指向父组件,以免在子组件中使用函数时this指向不是我们所期望的。(比如期望在子组件内通过调用父组件方法来修改父组件的this.state,结果没绑定导致this指向子组件,自然无法修改父组件this.state)
- 原因:绑定
react事件绑定函数传参2种情况
父组件绑定this时传参
- 在React这个例子中,在父组件中使用
bind绑定事件函数handleItemDelete的this指向时,如果还想将参数index传入函数,则可在绑定时传入:1
2// 这个例子里该组件在父组件中调用
<List.Item onClick={this.handleItemDelete.bind(this, index)}>{item}</List.Item>
父组件绑定this,子组件传参
- 但如果事件函数和bind绑定都在父组件中,而函数的调用和传参在子组件,就可以这样传参(可参考完整例子):
- 在父组件的构造函数中使用bind绑定
this.handleItemDelete=this.handleItemDelete.bind(); - 我们知道
bind()返回的还是一个函数,所以在子组件中,我们通过箭头函数在每次调用handleItemDelete()时传入参数index:1
2// 这个例子里该组件在子组件中调用
<List.Item onClick={()=>{this.props.handleItemDelete(index)}}>{item}</List.Item>
- 注意:
- 在这里不能直接使用
handleItemDelete(index)传参是因为handleItemDelete(index)直接执行了函数,而onClick需要绑定的事件函数是不能立即执行的,所以需要新建一个箭头函数让他不立即执行。 - **箭头函数是JS表达式,在JSX中需要使用
{}**,调用的父组件的函数也是JS表达式,同样中需要使用{}。
vue element-ui中自定义form表单rules
- 基础使用可参考element-ui文档
- 自定义rules时,我们可以把常用的规则封装到函数
validatePositiveNum()内,再将不同的提示语作为this传入封装的函数validatePositiveNum()内,这样就不会干扰到element-ui中自定义rules的校验函数原本传入的参数_rule, value, callback - 例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// computed内
rules() {
// rule, value, callback是校验函数原本自带的传入参数
const validatePositiveNum = (rule, value, callback) => {
const reg = /^[+]{0,1}(\d+)$|^[+]{0,1}(\d+\.\d+)$/; // 检验正数
if (!value) { // value是表单输入值
callback() // 正常,无提示
return
}
if (!reg.test(value)) {
const error = this ? new Error(this) : '请输入正数';
callback(error); // 表单下方出现提示语
} else {
callback(); // 正常,无提示
}
}
const rules = {
weight: [
// 使用bind就可以在不影响自带传入的那3个参数的前提下,传入提示语
{ validator: validatePositiveNum.bind('重量必须为正数'), trigger: ['change', 'blur'] }
],
}
return rules
},