• 售前

  • 售后

热门帖子
入门百科

详解React中的this指向

[复制链接]
hdnnuz62 显示全部楼层 发表于 2021-10-26 14:07:03 |阅读模式 打印 上一主题 下一主题
目次


  • 因由:
  • 颠末:

    • 1.构造函数
    • 2.render 函数
    • 3.bind 和箭头函数

  • 效果:

    • 方法一:在构造函数中利用bind
    • 方法二:将箭头函数赋值给类的属性

  • 注意:性能存在差异
计划记流水账一般细数一下 React 中的 this 指向标题,详细流程按事件三要素:因由,颠末,效果。哈哈哈哈哈!

因由:


众所周知,React 的设计是响应式的,利用者无需利用 DOM,利用数据,页面就会渲染更新。
数据一变就更新,是更新所有的 DOM 吗?固然不是,哪些变了就重新渲染哪些。那就要对数据厘革前后的 DOM 举行比力。直接对比真实 DOM 吗?如许性能会很低,React 比力的是假造 DOM,假造 DOM 也是对象,只不过相较真实 DOM而言,少了很多属性,更“轻”。
怎样写假造 DOM 呢?原生JS我们可以利用 document.createElement() 方法,创建节点。React 中也可以通过 React.createElement(component, props, children),但是呢这种写法遇见多层嵌套,就能让人眼花缭乱。于是 JSX “横空出世”,JSX 着实就是,React.createElement 的语法糖,但是我们用起来更加方便,可以直接写成 <p id="test">hello</p> 这种情势。
但是呢标题又又来了!JSX 语法是不被 webpack 辨认的,webpack 默认只能处置惩罚 .js 后缀名的文件,所以须要借助 Babel 这个 JavaScript 编译器,而 babel 开启了严格模式 **
  1. import React, { Component } from 'react'
  2. export default class index extends Component {
  3.     // speak(){
  4.     //     console.log(this)//输出undefined
  5.     // }
  6.     speak = () => console.log(this)//输出该组件
  7.     render() {
  8.         return (
  9.             <div>
  10.                 <button onClick={this.speak}>按钮</button>
  11.             </div>
  12.         )
  13.     }
  14. }
复制代码
this 本质上就是指向它的调用者,this 是在函数运行时才绑定,JS 里边平凡函数都是 window 调用的,所以指向 window,开启了严格模式之后是 undefined。
  1. (function(){
  2.     console.log(this)//window
  3. })()
复制代码
在 JSX 中通报的事件不是一个字符串(在原生 JS 的中监听事件,采取的是回调函数的情势,在Vue中给监听事件通报的是字符串变量),而是一个函数(如上面的:onClick={this.speak}),此时onClick即是中心变量,终极是由React调用该函数,而因为开启了严格模式的缘故,this 是undefined,所以处置惩罚函数中的this指向会丢失。

颠末:


究竟上我们须要的是 this 指向当前实例化对象,无疑会使代码编写方便很多。类式组件里边有两地方的this恰好指向当前实例化对象。

1.构造函数


类式组件里面的构造器里面的this是指向实例对象的,这是 ES6 类的特性,
众所周知 Javascript 里面是没有像 C++,JAVA 里面的的类的概念,ES6 类的实现也是基于原型链来实现的,
在 ES6 从前实例化一个对象应该如许:
  1. function Animal(name, age) {
  2.   this.name = name
  3.   this.age = age
  4. }
  5. Animal.prototype.say = function () {
  6.   console.log(this.name)
  7. }
  8. const Dog = new Animal('dog', 3)
  9. Dog.say()  //会在控制台打印出dog
复制代码
其中的 new 运算符,先产生了一个空对象 {},然后天生一个 this 指针,将 this 指针指向这个空对象;运行构造函数时,就相当于{}.name=dog,{}.age=3一样的为这个对象动态添加属性。最后将这个天生好的对象付给 Dog,
当我们利用 ES6 的 class 来声明上面这个类的话,代码如下:
  1. class Animal {
  2.   constructor(name, age) {
  3.     this.name = name
  4.     this.age = age
  5.   }
  6.   say() {
  7.     console.log(this.name)
  8.   }
  9. }
  10. const Dog = new Animal('dog', 3)
  11. Dog.say()  //会在控制台打印出dog
复制代码
类实现和上面应该大差不差,所以this是指向实例对象的。

2.render 函数


render 函数里面的 this,也是指向实例的。为啥呢?
起首 render 方法是在类式组件的原型上边的,React发现组件是利用类界说的时候,后边就会 new 出来该类的实例,注意这个实例是 React 帮你 new 出来的,随后实例调用 render 方法,将假造 DOM 转换为真实 DOM,所以 render 中的this 就是指向实例咯,究竟是他调用的嘛!,类似的呢,render 是一个生命周期钩子,那其他的生命周期钩子里面的 this也是指向实例组件的。

3.bind 和箭头函数


办理 this 标题呢,要有两个知识储
(1)bind
call apply bind 都是界说在函数原型上边的,用来改变函数 this 指向,传入的第一个参数是 this,后面的参数就是fun1的参数
区别:
       
  • call 和 bind 传给调用的函数是可以传多个 apply 则是将参数放进一个数组   
  • call 和 apply 返回立刻实行函数,bind 返回新的函数,bind()() 也是立刻实行   
  • 利用 bind 绑定 this 后,该函数里面的 this 不能厘革了,岂论是谁调用
  1. let aa = {
  2.     fun1: function(a,b){
  3.         console.log(this)
  4.         console.log(a-b);
  5.     }
  6. }        
  7. let bb = {
  8.     fun2: function(a,b){
  9.         console.log(this)
  10.         console.log(a+b);
  11.     }
  12. }
  13. aa.fun1.call(bb,11,22);//bb-11
  14. bb.fun2.apply(aa,[11,22]);//aa 33
  15. aa.fun1.bind(bb,11,22)();//bb -11
复制代码
(2)箭头函数
箭头函数:箭头函数并不会创建自己的实行上下文,所以箭头函数中的this都是外层的this,会向外作用域中,一层层查找this,直到有 this 的界说
  1. const A = {
  2.     arrow:() =>{
  3.         console.log(this)//window
  4.     },
  5.     func:function(){
  6.         this.arrow()//window
  7.         console.log(this)//A
  8.         setTimeout(() => {
  9.             console.log(this)//A
  10.         });
  11.     }
  12. }
  13. A.arrow()
  14. A.func()
复制代码
效果:


办理方法俺会两,嘿嘿!

方法一:在构造函数中利用bind
  1. import React, { Component } from 'react'
  2. export default class index extends Component {
  3.     constructor(){
  4.         super()
  5.         this.speak = this.speak.bind(this)
  6.         /*解决类中的this问题:this.speak = this.speak.bind(this),构造器里面的this默认指向实例对象,
  7.       实例对象通过原型链在类的原型上找着fnc函数,通过bind函数将其this指向改为实例对象,并返回一个新的函数
  8.       再将这个新的函数给实例,并取名为fnc*/
  9.     }
  10.     speak(){
  11.         console.log(this)//输出当前实例对象
  12.     }
  13.     render() {
  14.         return (
  15.             <div>
  16.                 <button onClick={this.speak}>按钮</button>
  17.             </div>
  18.         )
  19.     }
  20. }
复制代码
方法二:将箭头函数赋值给类的属性
  1. import React, { Component } from 'react'
  2. export default class index extends Component {
  3.     speak = () =>{
  4.         console.log(this)
  5.     }
  6.     render() {
  7.         return (
  8.             <div>
  9.                 <button onClick={this.speak}>按钮</button>
  10.             </div>
  11.         )
  12.     }
  13. }//需要传参的话,可以使用函数柯里化的思想
复制代码
注意:性能存在差异


利用箭头函数来办理性能会比力低,因为箭头函数不是方法,它们是匿名函数表达式,所以将它们添加到类中的唯一方法是赋值给属性。前面先容ES6的类的时候可以看出来,ES 类以完全差别的方式处置惩罚方法和属性
方法被添加到类的原型中,而不是每个实例界说一次。
类属性语法是为类似的属性分配给每一个实例的语法糖,实际上会在 constructor里面如许实现:
  1.     constructor(){
  2.         super()
  3.         this.speak = () => {console.log(this)}
  4.     }
复制代码
这意味着新实例被创建时,函数就会被重新界说,丢失了JS实例共享原型方法的上风。而方法一,只是在天生实例时多了一步 bind 操作,在服从与内存占用上都有极大的上风
以上就是详解React中的this指向的详细内容,更多关于React中的this指向的资料请关注草根技能分享别的相干文章!

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作