先来看一个现象,初学React的肯定会遇到在constructor进行bind的操作
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的, bind是永久绑定
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
//如果不bind, 这里的this是undefined, 因为回调用函数是系统调用的,不是某个对象调用的
//console.log(this.__proto__ === Toggle.prototype)
//console.log(this.constructor === Toggle.prototype.constructor)
//打印分析一下原型链
console.log(this)
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
export default Toggle;
bind 改变this是永久绑定,绑定后不能更改
function bindDemo(){
console.log(this)
}
var myObj = {
sex: 'f'
}
var bin = bindDemo.bind(obj)
bin()
//bind是永久绑定的,再调用call/apply都不能改变this指向
bin.call(myObj)
bindDemo.call(myObj)
函数返回值中的this,除了return对象返回对应的对象外,其它都指向当前对象
function fn() {
this.user = '前端食堂a'
//return function(){}
//return undefined
return null
}
var a = new fn()
console.log(a.user)
箭头函数中的this
var user = {
name: 'zlw',
callback1(){
//callback1这个函数产生了新的作用域 create a new scope,谁调用就指向谁
console.log(this)
},
callback2: () => {
//callback2这里没有产生新作用域 did not create a new scope ,因为箭头函数没有this这个隐形参数,调用的是上一层作用域
console.log(this)
}
}
var obj = {name:'ttt',age:33}
// call/apply/bind这些绑定本质是改变绑定对象
// window.user.callback1()
// user.callback1()
// user.callback1.call(obj)
// user.callback1.apply(obj)
//apply,call都不能改变this指向
//user.callback2()
user.callback2.call(obj)
//user.callback2.apply(obj)
//user.callback1(() => {console.log(this)})
再看一个例子
var obj1 = {
count: 10,
/*
doSomethingLater: function() {
console.log(this)
//since the arrow function was created within the "obj"
//即箭头函数在哪里定义的,this就指向哪个作用域
// setTimeout(() => {
// this.count++
// console.log(this.count)
// }, 2000)
//但凡创建一个函数就会创建新的相应的作用域链,这里的回调函数是系统调用的,指向window
setTimeout(function() {
console.log(this)
this.count++
console.log(this.count)
}, 2000)
}
*/
//这里箭头函数也是在obj里定义的,为何不指向obj ?
//这里因为obj定义的时候没有产生新的作用域,上例中定义了一个函数,产生了新作用域
//这里箭头函数不能用来函数声明,可以用作函数表达式
doSomethingLater: () => {
//打印window
console.log('i am ' + this)
// setTimeout(() => {
// console.log('you are ' + this)
// }, 2000);
//打印window
setTimeout(function(){
console.log('you are ' + this)
}, 2000);
}
}
obj1.doSomethingLater()
call/apply与bind区别
function bindDemo(){
console.log(this)
}
var myObj = {
sex: 'f'
}
var bin = bindDemo.bind(obj)
bin()
//bind是永久绑定的,再调用call/apply都不能改变this指向
bin.call(myObj)
bindDemo.call(myObj)
本文由 dealdot <dealdot#163.com> 创作, Full Stack Developer @ DeepBlue
本文最后编辑时间为: Apr 18, 2021 at 09:22 am
转载请注明来源