this的指向:
- 在全局环境下,无论是否是严格模式,this都指向全局,即windows
- 普通函数的指向:当函数被正常直接调用的时候,在严格模式下,this指向undefinde;在非严格模式下,this指向windows
- 通过类的实例对象调用类中的方法时,this指向的是类的实例对象
- 嵌套函数中的this不会继承外层函数的this值
- 箭头函数不会创建自身的执行上下文,因此箭头函数中的this取决于他外部的函数
提出问题
使用一个小案例来理解在类方法中this的指向性问题
创建组件,当在类中为元素添加绑定事件changeWeather()时,触发单击事件的时候输出里面的this为undefined
<script type="text/babel">
//创建组件
class Weather extends React.Component{
constructor(props){
super(props)
//初始化状态
this.state = {isHot:false}
}
render(){
// console.log('render');
//读取状态
const {isHot} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h1>
}
changeWeather(){
console.log(this);
}
}
</script>
用以下代码片段来理解为什么this指向为undefined
<script type="text/javascript" >
class Person {
constructor(name,age){
this.name = name
this.age = age
}
study(){
//study方法放在了哪里?——类的原型对象上,供实例使用
//通过Person实例调用study时,study中的this就是Person实例
console.log(this);
}
}
const p1 = new Person('tom',18)
p1.study() //通过实例调用study方法
</script>
当通过p1.study()调用study方法的时候,是通过类的实例对象调用类中的方法,因此this的指向是类的实例对象,当我们在下方输入这两行代码时
const x = p1.study
x()
此时输出结果是undefined,因为此时,是将Person实例对象调用的study方法赋值给x,而x直接调用study方法,不是通过Person的实例对象去调用study,属于函数的直接调用,那么在这个时候this的指向应该为windows,但由于在类中所定义的方法在局部已经开启了严格模式,所以最终所输出的结果为undefined
同理
onClick={this.changeWeather} 相当于将changeWeather()方法赋值给onClick,onClick直接调用该方法
而由于类中开启了局部严格模式,再加上babel解析代码的时候也开启严格模式,导致此时的this指向变为undefined
解决方法
//在构造器中添加
this.changeWeather = this.changeWeather.bind(this)
bind做了两件事:
- 返回一个新的函数(changeWeather)
- 修改this的指向:将this变为weather的实例对象
这行代码将整个函数放到了命名为changeWeather()的新函数身上,并且将这个新返回的函数放到this的实例对象身上,且这个新函数中的this指向的是weather的实例对象
此时就成功解决了this的指向性问题