由React类组件中的this指向问题,引发的一系列学习

前言

前段时间用React写了些页面,但我们目前的项目还主要是Vue2,为防止忘得一干二净,又刷了遍基础知识。

在写类组件的时候,一不小心又碰到了this指向问题...

kotlin 复制代码
   changeName () {
       this.setState({
           name: 'xxx'
       })
   }

这种写法会直接报this是undefined

一、this指向undefined问题

针对类组件中,事件处理函数中this为undefined问题,可以通过3种方法改变

1.箭头函数(这种方式应该较多一些)

javascript 复制代码
   changeName = () => {
       this.setState({
           name: ''
       })
  }
   

箭头函数没有this, 因此会向上找,直到window。

2.在调用事件处理函数时,直接通过箭头函数调用

scala 复制代码
import React from "react"
class Pfs extends React.Component {
  // 定义组件状态
  state = {
    name: 'cp teacher'
  }
  changeName () {
    this.setState({
      name: '测试更改state中的name'
    })
  }
  render () {
    return (
      <div>This is testComponent
        当前name为: {this.state.name}
        <button onClick={() => this.changeName()}>更改name</button>
      </div>
    )
  }
}
export default Pfs

3.使用bind修改this指向

scala 复制代码
import React from "react"
class Pfs extends React.Component {
  constructor() {
    super()
    this.changeName = this.changeName.bind(this)
  }
  // 定义组件状态
  state = {
    name: 'cp teacher'
  }
  changeName () {
    this.setState({
      name: '测试更改state中的name'
    })
  }
  render () {
    return (
      <div>This is testComponent
        当前name为: {this.state.name}
        <button onClick={this.changeName}>更改name</button> //注意,这里的调用方式也变了
      </div>
    )
  }
}
export default Pfs

二、JS中的bind

case1:

php 复制代码
function fn (num) {
    console.log(this, num)
}
fn()

可以看到this指向window,调用fn时,因为未传参,所以num为undefined。

case2:

javascript 复制代码
var obj = {
  a: 1
}
function fn (num) {
  console.log(this, num)
}
fn.bind(obj, 1)()

由上图可以看到bind改变了this的指向,由window转为指向了obj。至于为什么后面还要加一个(), 是因为bind返回的是一个函数,而不是函数执行的结果。必须加一个(),函数才能执行起来。

case3:

javascript 复制代码
var obj = {
  a: 1
}
function fn (num1,num2) {
  console.log(this, num1,num2)
}
fn.bind(obj, 1)(2)

由上图可知,传参可以分批传。

二、自己实现bind

参考链接:zhuanlan.zhihu.com/p/266798352

step1: 由于bind是由函数调用,因此自己实现的bind要加在function的原型上

javascript 复制代码
function myBind () {

}
Function.prototype.myBind = myBind

step2: bind要改变this的指向,我们要把myBind的第一个参数设置成context,即改变this指向后的对象,默认值是window。

ini 复制代码
function myBind (context=window) {

}
Function.prototype.myBind = myBind

step3: bind要传入返回函数的参数,但这个参数的数量是不固定的,因此用扩展运算符处理

javascript 复制代码
function myBind (context=window, ...outerArg) {
    return function () {
    
    }
}
Function.prototype.myBind = myBind

step4: 这里要介绍JS中的call()方法,call用于调用一个函数,并将指定的对象作为函数的上下文(this值),除了指定上下文外,还可以将参数作为一个列表传递给该方法。

vbnet 复制代码
function.call(thisArg, arg1, arg2, ...)

thisArg: 在函数执行时作为this值绑定到函数的对象

arg1, arg2,...要传递给函数的参数。

!!!! 在用 bind 的时候,比如 fn.bind(),我们返回的函数其实就是 fn 本身,只是改了 this 而已 ,所以,为了获取到 fn,我们需要在 myBind 里用 this 拿到这个 fn。需要注意的是,匿名函数中的 this 指向并不是 fn,而是 window 。另一点是,myBind 自己可以传参,内部的匿名函数也可以,根据 例3,我们了解到 bind 可以分批传参的特点,因此,我们需要把外部参数和内部参数利用 concat 组合起来

重点就是如下代码:

javascript 复制代码
function myBind(context=window,...outerArg){
let _this = this;
return function(...innerArg){
               _this.call(context,...innerArg.concat(outerArg))
           }
       }
Function.prototype.myBind=myBind;

最后测试

javascript 复制代码
function myBind(context=window,...outerArg){
  let _this = this;
  console.log('_this', _this)  //f fn(num){console.log(this,num)}
  return function(...innerArg){
      _this.call(context,...innerArg.concat(outerArg))
  }
}
Function.prototype.myBind=myBind;

function fn(num){
  console.log(this,num)
}
fn.myBind({a:1},50)();

其中,myBind的这套方法对应一个专有名词,叫柯里化函数思想

二、柯里化

参考链接: juejin.cn/post/701656...

相关推荐
耶啵奶膘20 分钟前
uniapp-是否删除
linux·前端·uni-app
王哈哈^_^2 小时前
【数据集】【YOLO】【目标检测】交通事故识别数据集 8939 张,YOLO道路事故目标检测实战训练教程!
前端·人工智能·深度学习·yolo·目标检测·计算机视觉·pyqt
cs_dn_Jie2 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic3 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿3 小时前
webWorker基本用法
前端·javascript·vue.js
cy玩具4 小时前
点击评论详情,跳到评论页面,携带对象参数写法:
前端
qq_390161774 小时前
防抖函数--应用场景及示例
前端·javascript
John.liu_Test5 小时前
js下载excel示例demo
前端·javascript·excel
Yaml45 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
PleaSure乐事5 小时前
【React.js】AntDesignPro左侧菜单栏栏目名称不显示的解决方案
前端·javascript·react.js·前端框架·webstorm·antdesignpro