react里面的this_浅谈react 中的 this 指向

前言 最近在做一个项目的时候 关于class方法中 this 指向以及 外置prototype 的 this 指向 引发了我的思考!

image.png

ES6原生class

我们假设 A 为 react B 为 我们创建的类 class B extends React.component{}

class A {

constructor() {

this.x = 1;

}

}

class B extends A {

constructor() {

super();

this.x = 2;

console.log('=====');

console.log(this); // B

console.log(this.x); // 2

console.log(super.x); // undefined

this.getme = this.getme.bind(this)

}

getName(){

console.log('getName');

console.log(this.x); // B

let m = this.getme

m()

}

getme(){

console.log('getme');

console.log(this.x); // B

}

}

// 类转化为 es5的写法如下:

function Es5B() {

this.x = 2

}

Es5B.prototype.getName = function () {

console.log(this);

console.log('getName');

console.log(this.x);

}

let b = new B();

b.getName()

let esb = new Es5B()

esb.getName()

打印结果

image.png

经过打印我们发现 B 中的 this 指向的都是 B 这个类

那么问题来了,我们 都知道 react的 class 中需要绑定 this, 为什么需要?绑定 this 有哪些方式,以及这些方式有什么不同?

http://note.youdao.com/noteshare?id=3d64b603405bcbb2c3cad3f750e5341d

react 高阶 api => createElement

jsx 语法

class Hello extends React.Component {

render() {

return

Hello {this.props.toWhat}
;

}

}

ReactDOM.render(

,

document.getElementById('root')

);

编译成下面这段代码

class Hello extends React.Component {

render() {

return React.createElement('div', null, `Hello ${this.props.toWhat}`);

}

}

ReactDOM.render(

React.createElement(Hello, {toWhat: 'World'}, null),

document.getElementById('root')

);

看我们最初的那一段代码

// 如果我们将 constructor 中的那个 bind 去掉之后

// this.getme = this.getme.bind(this)

// 执行到这里 this的指向就变化了

let m = this.getme

m() // 此时 this 变化为 undefined

将方法进行赋值之后,丢失了上下文,导致 this 变成 undefined , this之所以没有变为window 是因为类声明和类表达式的主体以 严格模式 执行,主要包括构造函数、静态方法和原型方法。Getter 和 setter 函数也在严格模式下执行。

未解之谜 原生 class 中 如果方法改为箭头函数这种形式就会报错 但是在 react 的 class 中 是可以正常渲染的

class A {

constructor() {

this.x = 1;

}

}

class B extends A {

constructor() {

super();

this.x = 2;

}

getme=()=>{ // 这里会报错误

console.log('getme');

console.log(this.x);

}

getName(){

console.log('getName');

console.log(this.x);

let m = this.getme

m()

}

}

let b = new B();

b.getName()

内置箭头函数与外置箭头函数是有区别的

class B extends A {

constructor() {

super();

this.x = 2

}

getName(){

console.log('getName');

console.log(this.x); // B

let m = this.getme

m()

}

}

B.prototype.getme = ()=> {

console.log('getme');

console.log(this);

/*

箭头函数的 this 指向定义时所在对象 定义的环境在 window

此时 this 指向 window

如果是 react 创建的组件 此时 this指向和类之外的 this 是一致的 (但不是 window)

如果prototype上挂载方法的时候 强烈建议大家用es5的方式就好!

*/

}

let b = new B();

b.getName()

react 创建组件(需要绑定 this 和绑定 this 的方法)

export default class ExtendsCompTable extends React.Component {

constructor (props) {

super(props)

this.state = {

name: 'react测试this指向'

}

this.handler = this.handler.bind(this)

}

handler () {

message.info('点击了 bindthis),通过 bind 绑定 this')

}

renderDom () {

let { name } = this.state

return {name}

}

handlerArrow=()=> {

console.log(this);

message.info('点击了箭头函数绑定按钮,通过箭头函数绑定 this')

}

handleInnerArrow(){

console.log(this);

message.info('点击了箭头函数绑定,通过 bind 绑定 this')

}

handleBind(){

console.log(this);

message.info('点击了bind')

}

render () {

return (

234567890

bind(this)

{/* 这种直接调用的方式不需要绑定 this 作为对象的方法被调用 this 指向对象*/}

{this.renderDom()}

{/* 这种 handlerArrow=()=> {...}的形式 虽然可以用 但是不太建议*/}

箭头函数绑定

{

this.handleInnerArrow()

}}>点击触发方法

bind

)

}

}

箭头函数 ()=>

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,this是继承自父执行上下文!!中的this

var x=11;

var obj={

x:22,

say:function(){

console.log(this.x)

}

}

obj.say(); // 22

var x=11;

var obj={

x:22,

say:()=>{

console.log(this.x);

}

}

obj.say();// 11

var a=11

function test1(){

this.a=22;

let b=function(){

console.log(this.a);

};

b();

}

var x=new test1(); // 11

var x=11;

var obj={

x:22,

say:()=>{

console.log(this.x);

}

}

obj.say(); // 22

箭头函数中的 this 对象指向是固定的

不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误

bind

无论是 call() 也好, apply() 也好,都是立马就调用了对应的函数,而 bind() 不会, bind() 会生成一个新的函数,bind() 函数的参数跟 call() 一致,第一个参数也是绑定 this 的值,后面接受传递给函数的不定参数。 bind() 生成的新函数返回后,你想什么时候调就什么时候调

var m = {

"x" : 1

};

function foo(y) {

alert(this.x + y);

}

foo.apply(m, [5]);

foo.call(m, 5);

var foo1 = foo.bind(m, 5);

foo1();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值