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
},