资讯专栏INFORMATION COLUMN

ES6的class本质和react中需要使用bind(this)的原因

AlphaGooo / 1109人阅读

摘要:语法糖可以说是广泛存在于各种计算机代码中,包括语言中的其实就是的语法糖。在执行的时候,如果执行了,那么从中获取的函数,其对象已经被绑定到了的即上。

ES6的class

我们知道ES6新出一个规范是使用class关键字来定义一个类,这在以前是没有的
在以前,需要在javascript里实现面向对象,就需要使用prototype

什么是面向对象?

面向对象有如下几个基本特征,通常认为,只要实现了这几个特性,就认为是实现了面向对象:
1.封装
2.继承
3.多态
这里不对三个基本特征的做详细展开。只需要知道,javascript实现继承和多态都需要用到prototype
而ES6的class,本质上还是ES5的prototype的语法糖

什么是语法糖?

语法糖就是提供了一种全新的方式书写代码,但是其实现原理与之前的写法相同。
语法糖可以说是广泛存在于各种计算机代码中,包括C语言中的a[i]其实就是*a+i的语法糖。而今天对于我们来说,a[i]其实已经很普遍和常用了,所以也没有人提这是语法糖这回事了。因为终极来说,所有语言都是汇编语言的语法糖:)

class foo{
    constructor(){
    }
    a(){}
    b(){}
}

// 等价于
function foo(){};
foo.prototype = {
    constructor(){},
    a(){},
    b(){},
}
ES6的class跟ES5的定义方式用几个不同

1.没有变量提升
2.this指向不同

先来看1:

test(); // 输出"test"
function test(){
    console.log("test");
}

我们知道即便在定义test函数之前执行test(),也是会得到结果的。这是因为解析javascript代码的时候会把所有的function test(){}这类代码(即正常定义函数)都提升到最上方去定义。

但是这么执行不行:

let a = new test(); // 报错
class test(){} 

再看2:

class Animal {
    printName () {
      this.print("Hello animal");
    }
    print(name) {
      console.log(name);
    }
}
const animal = new Animal();
animal.printName(); // 输出"Hello animal"
const { printName } = animal;
printName(); // 报错: Cannot read property "print" of undefined

如果执行了bind

class Animal {
    constructor(){
        this.printName = this.printName.bind(this);
    }
    printName () {
      this.print("Hello animal");
    }
    print(name) {
      console.log(name);
    }
}
const animal = new Animal();
animal.printName(); // 输出"Hello animal"
const { printName } = animal;
printName(); // 输出"Hello animal"
发生了什么?

animal中的printName函数的this原本指向的是执行环境,如果不执行bind,那么printName函数的this指向window。
在执行new Animal()的时候,如果执行了bind,那么从animal中获取的printName函数,其this对象已经被绑定到了constructor的this,即animal上。
以下是this的指向

那么我们为什么需要在react里bind(this)呢?

简单来说,就是react在调用render方法的时候,会先把render里的方法赋值给一个变量(比如变量foo),然后再执行foo()。
具体来说,以典型的绑定点击事件为例

react构建虚拟DOM的时候,会把this.clickHandler先赋值给一个变量。我们假设是变量clickFunc = this.clickHandler;
然后,把虚拟DOM渲染成真实DOM的时候,会把onClick属性值替换成onclick,并给onclick赋值clickFunc

在复杂的情况中,可能存在多次传递,如果不进行bind,那么this的指向是一定会丢失的。

为什么react不自己集成bind到生命周期里?

1是,没有特别合适集成bind的地方
2是,并不是所有的函数都需要bind
3是,随意集成bind可能导致效率低下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104208.html

相关文章

  • React.createClassextends Component区别

    摘要:本质上是一个工厂函数,的方式更加接近最新的规范的写法。两种方式在语法上的差别主要体现在方法的定义和静态属性的声明上。和的区别主要在于语法区别和状态的区别区别语法区别后一种方法使用的语法,用构造器来构造默认的属性和状态。 createClass本质上是一个工厂函数,extends的方式更加接近最新的ES6规范的class写法。两种方式在语法上的差别主要体现在方法的定义和静态属性的声明上。...

    hlcc 评论0 收藏0
  • React&ES6

    摘要:在中必须调用方法,因为子类没有自己的对象,而是继承父类的对象,然后对其进行加工而就代表了父类的构造函数。虽然代表了父类的构造函数,但是返回的是子类的实例,即内部的指的是,因此在这里相当于。要求,子类的构造函数必须执行一次函数,否则会报错。 1.class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES...

    jeffrey_up 评论0 收藏0
  • React&ES6

    摘要:在中必须调用方法,因为子类没有自己的对象,而是继承父类的对象,然后对其进行加工而就代表了父类的构造函数。虽然代表了父类的构造函数,但是返回的是子类的实例,即内部的指的是,因此在这里相当于。要求,子类的构造函数必须执行一次函数,否则会报错。 1.class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES...

    mist14 评论0 收藏0
  • 谈一谈创建React Component几种方式

    摘要:用这种方式创建组件时,并没有对内部的函数,进行绑定,所以如果你想让函数在回调中保持正确的,就要手动对需要的函数进行绑定,如上面的,在构造函数中对进行了绑定。 当我们谈起React的时候,多半会将注意力集中在组件之上,思考如何将页面划分成一个个组件,以及如何编写可复用的组件。但对于接触React不久,还没有真正用它做一个完整项目的人来说,理解如何创建一个组件也并不那么简单。在最开始的时候...

    mylxsw 评论0 收藏0
  • React类,方法绑定(第三部分)

    摘要:使用箭头函数和构造函数当方法被调用时,会保留上下文。我们能使用这个特征用下面的方法在构造函数中重定义函数。在调用方法的方使用函数绑定语法你也可以直接在非构造函数里面的里面直接使用函数绑定。 这是React和ECMAScript6/ECMAScript7结合使用系列文章的第三篇。 下面是所有系列文章章节的链接: React 、 ES6 - 介绍(第一部分) React类、ES7属性初始...

    livem 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<