码迷,mamicode.com
首页 > 其他好文 > 详细

神出鬼没的this

时间:2020-07-27 23:38:30      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:ring   bin   define   com   car   text   get   fine   tps   

技术图片

神出鬼没的this

上一篇挖了个坑,今天给补上

你是不是也曾像我一样:

编写了个函数明明可以正常工作,但是一做为事件回调函数就报undefind

在编写React组件时,看到在构造函数中还得对每个方法bind一下 :

this.funOne = this.funOne.bind(this);
this.funTwo = this.funTow.bind(this);

多么奇怪的写法,为啥子还要再bind下呢? 不如删了,然后就各种undefined

要理解为什么会undefined还得从this说起:

var name = ‘tianlang‘;
function getName() {
    console.log(this.name);
}
getName();

这段代码会输出:

tianlang

我们只需加一行看是不相关的代码,就能让它报undefined:

var name = ‘tianlang‘;
function getName() {
    ‘use strict‘
    console.log(this.name);
}
getName();

VM412:4 Uncaught TypeError: Cannot read property ‘name‘ of undefined
at getName (<anonymous>:4:22)
at <anonymous>:6:1
getName @ VM412:4
(anonymous) @ VM412:6

只因在人群中多看了你一眼,就在代码中多写了行use strict整个程序都崩溃了。

JavaScript执行引擎看到我们写了use strict就启用了严格模式,严格模式下函数getName中的this指向undefind

,在非严格模式下getName中的this指向全局变量(在浏览器运行环境中就是window, 在node运行环境中就是global)。

就这么简单? 这也不神出鬼没啊。 鬼那能容易看到,如果那么容易看到也就不叫鬼了,接着往下面看:

var name = ‘tianlang‘
var person = {
    name: ‘tianlangstudio‘
}
function getName() {
    console.log(this.name);
}
person.getName = getName;
person.getName();
getName();

你可以猜下,在看执行结果:

tianlangstudio

tianlang

同样是调用getName为什么获取的name不一样呢?

这是因为函数中的this是执行函数调用者的。当我们使用person.getName的方式执行时getName中的this就指向了person.

只有在直接执行函数又没有手动绑定操作(后面会介绍)又在非严格模式下this才指向全局变量.

也就是函数内的this具体执行谁跟调用的方式有关。不信你可以再添加两行代码试下:

var personGetName = person.getName;
personGetName();

执行结果是:

tianlang

这就是为什么定义的函数明明可以正常执行,但是一做为事件回调函数就报undefind了。

就像这样:

someHtmlDomNode.addEventListener(‘click‘, person.getName);

你可以认为person.getName被赋值给了一个变量personGetName 再事件触发时实际是执行的personGetName(). 不再是person.getName这种样式的了,它变了。

那怎么让它还是以person.getName的方式被调用呢?可以再外面包个函数,或者使用手动绑定操作:

someHtmlDomNode.addEventListener(‘click‘, funciton() {
                                 person.getName()
});
someHtmlDomNode.addEventListener(‘click‘, person.getName.bind(person));

这就是为什么定义React组件时为什么还需要对每个方法再bind次了。bind操作就是手动为函数指定this

。除了bind还有callapply也可以为函数指定执行时的this值。不同的是bind的返回值是一个新的函数,你可以在你乐意的时候再执行这个函数而callapply是绑定和执行一起执行的,所以它们接受不只一个参数。除了跟bind一样需要一个参数作为this还需要函数运行所需要的参数,这也是applycall不一样的地方,一个接受数组作为执行函数的参数,一个是使用任意个参数的形式。

fun.apply(thisObj, [‘arg1‘, ‘arg2‘])

fun.call(thisObj, ‘arg1‘, ‘arg2‘, ‘arg3‘)

在React组件中写那么多看是无用的bind真的有点辣眼睛,有没有更好的方式解决呢?

可以实用箭头函数注册事件监听或定义方法,就像这个样子:

someHtmlDomNode.addEventListener(‘click‘, () => {
                                 this.getName()
});
class SomeClass {
    constructor(name) {
        this.name = name;
    }
    getName = () => this.name;
}
var obj1 = new SomeClass("tianlang");
obj1.getName();// tianlang
var objGetName = obj1.getName;
objGetName();//tianlang

简单说这是因为:

The best thing is that arrow functions couldn‘t care less about this! Practically, it means they are totally ignoring it (and maybe hoping this will go away), so the context of this right outside the arrow function stays the same inside it

哇! 该煮饭了,拜拜!

神出鬼没的this

标签:ring   bin   define   com   car   text   get   fine   tps   

原文地址:https://blog.51cto.com/14256460/2513634

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!