React类组件中this指向性问题
<body>
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="app"></div>
<script type="text/babel">
class Clock extends React.Component{
constructor(props){
console.log('constructor--');
super(props)
this.state = {
time:new Date().toLocaleTimeString()
}
console.log('constructor',this);
// go函数产生新的函数(已经绑定了this)=>新的go函数赋值给this.go属性上
this.go = this.go.bind(this)//指向新的函数,不再指向go() this.go()=新的函数(this指向组件实例)
}
go(){
console.log(this);//默认指向undefined
this.setState({time:new Date().toLocaleTimeString()})
}
render(){
console.log('render--');
console.log('render--',this);//当前组件实例,也是箭头函数(内部函数)this指向
return(
<div>
<h1>Clock</h1>
<h3>
time:{this.state.time}
</h3>
{/*go0:go中的this指向underfined*/}
<button onClick = {this.go}>指针走动go0</button>
{/*1:未点击就报错:内存溢出 react-dom.development.js:23833 Uncaught Error: Maximum update depth
花括号中是直接执行函数 不是绑定函数
this是组件实例,谁调用指向谁 this是当前组件实例
死循环:this.go()=>go()=>serStaet=>render=>this.go()死循环 内存溢出*/}
{/*<button onClick = {this.go()}>指针走动go1</button>*/}
<br />
<br />
{/*2: 执行函数
声明函数:const fn=()=>{}
执行函数:fn()
{箭头函数:this指向外围的作用域}
此外围作用域为render,this指向当前组件实例
问题:
2.1:函数是特殊对象,占用的是堆内存空间,重复声明会导致重新开辟新的内存空间,相对来说,性能相对比较差
2.2:JSX元素中添加了js逻辑代码,会导致代码复杂,臃肿,后期维护困难*/}
<button onClick = {()=>{
console.log("=>",this);
this.setState({time:new Date().toLocaleTimeString()})
}}>指针走动go001</button>
<button onClick = {()=>{
// 箭头函数中this指向render实例
this.go()
}}>指针走动go002</button>
<button onClick = {
function(){
// 方式不可行 this查找不到 会报错:Uncaught TypeError: Cannot read properties of undefine
console.log(this);//this指向underfined
this.setState({
time:new Date().toLocaleTimeString()
})
}
}>指针走动go003</button>
{/*3.通过bind的方式,手动改变this指向,解决了代码混乱的问题
bind原理:bind里面每次声明新的函数,新的函数指向手动改变this的指向,将其返回,每次都会重新绑定
问题:
bind重新绑定生成新的函数,占内存*/}
<button onClick ={this.go.bind(this,'可以传参')}>指针走动go004</button>
{/*4.一次性绑定,解决重复绑定问题
执行此阶段的时候 this.go = 函数(已经绑定好this)*/}
<button onClick ={this.go}>指针走动go005</button>
{/*5.es7新特性写法*/}
<button onClick ={this.go}>指针走动go006</button>
{/*go(){
console.log(this);//默认指向undefined
this.setState({time:new Date().toLocaleTimeString()})
}*/}
{/*或者是写道constructor中
this.go(){
console.log(this);//默认指向undefined
this.setState({time:new Date().toLocaleTimeString()}) }
*/}
</div>
)
}
}
ReactDOM.render(<Clock />,document.getElementById('app'))
</script>
</body>
运行页面:
JS中this指向性问题
1.普通函数
<script>
var name = 'jack'
var objX = {
name:'objxName',
sayName:function(){
// 普通函数
console.log(this.name);
}
}
var objY = {
name:'objyName'
}
objX.sayName() //输出:objxName
objX.sayName.call(objY) //this指向具体对象objY 输出:objy
objX.sayName.call() //指向全局对象window 输出:jack
// 普通函数this跟 调用对象函数 有关,谁调用指向谁;和改变this指向方法有关,有具体指向对象时this指向该对象;没有具体指向对象时,指向window
</script>
普通函数this跟 调用对象函数 有关,谁调用指向谁;和 改变this指向方法 有关,有具体指向对象时this指向该对象;没有具体指向对象时,指向window
2.箭头函数
<script>
var name = 'jack'
var objX = {
name:'objxName',
sayName:()=>{
// 箭头函数
console.log(this.name);
}
}
var objY = {
name:'objyName'
}
objX.sayName() //输出:jack
objX.sayName.call(objY) //输出:jack
objX.sayName.call() //输出:jack
// 箭头函数:
// 箭头函数中的this和 定义函数时所在作用域所指向的对象 (定义时所在作用域的外围环境就是this指向 外围的js对象 跟调用对象没有关系)在此处就是window
// 失效:调用失效&强制改变this指向也失效
</script>
箭头函数:
箭头函数中的this和 定义函数时所在作用域所指向的对象 有关 (定义时所在作用域的外围环境就是this指向 外围的js对象 跟调用对象没有关系) 在此处就是window
失效:调用失效&强制改变this指向也失效
3.没有显式调用
<script>
var name = 'jack'
var objX = {
name:'objxName',
sayName:function(){
// 普通函数
console.log(this.name);
}
}
objX.sayName() //输出:objxName
var copyFun = objX.sayName
copyFun()//输出:jack
//没有显示调用(显示调用:前面有具体的对象调用叫做显示调用)=>window调用=>谁调用this指向谁,this指向window
</script>
没有显示调用 (显示调用:前面有具体的对象调用叫做显示调用) =>window调用=>谁调用this指向谁,this指向window
4.严格模式
<script>
'use strict'
//开启严格模式,意味着this不会自动绑定到全局对象window
var name = 'jack'
var objX = {
name:'objxName',
sayName:function(){
// 普通函数
console.log(this.name);//Cannot read properties of undefined出错,找不到this
}
}
objX.sayName() //输出:objxName
var copyFun = objX.sayName
copyFun()//输出:undefined 相当于undefined.copyFun()=>copyFun.sayName=>this.name=>undefined.name
// 出现报错:TypeError: Cannot read properties of undefined
</script>
'use strict' :开启严格模式,意味着this不会自动绑定到全局对象window
5.es6 class语法
<script>
class C{
// es6语法
// 类通过new的方式调用
go(){
console.log(this);//C{}
}
// react:将自定义函数传给react,再去执行
callback(fun){
// 严格模式:使用es6 class中声明的方法自动使用了严格模式
//var fun = this.go => fun()隐式调用(this不会自动绑定window)
fun()//
}
render(){
// 将go函数转给react
this.callback(this.go)
}
}
var c = new C()
c.go()//输出:C{} this指向类的实例(类似类组件实例)
c.render() //undefind
</script>
使用es6 class中声明的方法自动使用了严格模式