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

栏目: JavaScript · 发布时间: 6年前

内容简介:我们知道ES6新出一个规范是使用class关键字来定义一个类,这在以前是没有的在以前,需要在javascript里实现面向对象,就需要使用prototype面向对象有如下几个基本特征,通常认为,只要实现了这几个特性,就认为是实现了面向对象:

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的指向

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

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

简单来说,就是react在调用render方法的时候,会先把render里的方法赋值给一个变量(比如变量foo),然后再执行foo()。

具体来说,以典型的绑定点击事件为例

<div onClick={this.clickHandler}></div>

react构建虚拟DOM的时候,会把this.clickHandler先赋值给一个变量。我们假设是变量clickFunc = this.clickHandler;

然后,把虚拟DOM渲染成真实DOM的时候,会把onClick属性值替换成onclick,并给onclick赋值clickFunc

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

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

1是,没有特别合适集成bind的地方

2是,并不是所有的函数都需要bind

3是,随意集成bind可能导致效率低下


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Applications (Hacking Exposed)

Web Applications (Hacking Exposed)

Joel Scambray、Mike Shema / McGraw-Hill Osborne Media / 2002-06-19 / USD 49.99

Get in-depth coverage of Web application platforms and their vulnerabilities, presented the same popular format as the international bestseller, Hacking Exposed. Covering hacking scenarios across diff......一起来看看 《Web Applications (Hacking Exposed)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码