zoukankan      html  css  js  c++  java
  • 浅谈箭头函数和setTimeout中的this


    箭头函数会改变this的指向,这个大家看文档都看到过,可是有没有具体理解呢?
    我发现自己应该可能大概是......emmmm,然后我整理了一遍,加强一下概念吧
    顺带再讲一下setTimeout这个函数改写this的概念

    首先分别讲一下两位主角

    • 箭头函数:都2019年了,大家肯定不陌生了,用法很简单,可以自行百度,箭头函数有一个很大的特性是会改写内部的this指向,那么实际运用的过程中你考虑过注意过这个问题吗?箭头函数内部的this会指向声明箭头函数时所在作用域的this(划重点!!接下来要记住!)
    • setTimeout:大家肯定都用过了,它的第一个参数是一个方法,传入的这个方法内部的this会被改写指向window(划重点!!接下来要记住!)

    一贯风格,我们上代码来看问题

    // 先给window加一个id,以便于确认之后this的指向
    window.id = 0;
    // 声明一个函数fn
    const fn = {
      id: 1,
      say: function() {
        console.log('id:', this.id);
      },
      sayArrow: () => {
        console.log('id:', this.id);
      },
      say1: function() {
        setTimeout(function() {
          console.log('id:', this.id);
        }, 1000);
      },
      say2: function() {
        let that = this;
        setTimeout(function() {
          console.log('id:', that.id);
        }, 1000);
      },
      say3: function() {
        setTimeout(() => {
          console.log('id:', this.id);
        }, 1000);
      },
      say4: () => {
        setTimeout(() => {
          console.log('id:', this.id);
        }, 1000);
      },
      say5: () => {
        setTimeout(function() {
          console.log('id:', this.id);
        }, 1000);
      },
    };

    好了,接下来大家来做题,不要做晕了哈

    fn.say();
    fn.sayArrow();
    setTimeout(fn.say, 1000);
    setTimeout(fn.sayArrow, 1000);
    setTimeout(() => fn.say(), 1000);
    setTimeout(() => fn.sayArrow(), 1000);
    fn.say1();
    fn.say2();
    fn.say3();
    fn.say4();
    fn.say5();

    以上各自输出什么呢?接下来核对下答案,如果全对,那ojbk了
    1 0 0 0 1 0 0 1 1 0 0
    如果觉得自己可能没摸透,可以多包几层作用域再试试

    接下来看代码讲原因!

    fn.say();
    /*
      结果: 1
      原因: 通过fn调用的say, say是 函数声明, this指向fn,输出的是fn.id
    */
    
    fn.sayArrow();
    /*
      结果: 0
      原因: 通过fn调用的say, say是 箭头函数声明, this指向箭头函数声明时作用域的this,也就是this指向window,输出的是window.id
    */
    
    setTimeout(fn.say, 1000);
    /*
      结果: 0
      原因: 通过setTimeout调用, setTimeout改写所传函数的this, 也就是this指向window,输出的是window.id
    */
    
    setTimeout(fn.sayArrow, 1000);
    /*
      结果: 0
      原因: 通过setTimeout调用, setTimeout改写所传函数的this, 也就是this指向window,输出的是window.id
    */
    
    setTimeout(() => fn.say(), 1000);
    /*
      结果: 1
      原因: 通过setTimeout调用, 但是fn.say()是被箭头函数包裹,所以fn.say()调用不受this改变的影响,原因参考第一句输出
      ps: 等同于 setTimeout(function () { fn.say(); } , 1000);
    */
    
    setTimeout(() => fn.sayArrow(), 1000);
    /*
      结果: 0
      原因: 同上雷同,具体原因可参考第二句输出
      ps: 等同于 setTimeout(function () { fn.sayArrow(); } , 1000);
    */
    
    fn.say1();
    /*
      结果: 0
      原因: setTimeout改写函数内部的this, 使其指向window, 输出window.id
    */
    
    fn.say2(); // 1
    /*
      结果: 1
      原因: setTimeout虽然改写函数内部的this,但是输出的是that.id,这个that在setTimout外面声明,指向的是fn,所以输出fn.id
    */
    
    fn.say3(); // 1
    /*
      结果: 1
      原因: fn.say3函数其内部的this指向的fn,而setTimeout内部传了一个箭头函数,箭头函数内部中的this就指向了fn.say3内的this,也就是fn,最后输出fn.id
    */
    
    fn.say4(); // 0
    /*
      结果: 0
      原因: fn.say4这个函数本身就是使用箭头函数声明,其内部的this指向的是箭头函数声明时所在的作用域,即window,而且setTimeout也是传了一个箭头函数,这里面的this指向外层箭头函数内部中的this,传引用也指向了window,最后输出window.id
    */
    
    fn.say5(); // 0
    /*
      结果: 0
      原因: fn.say5用箭头函数声明,其内部的this指向window,而且setTimeout也会改写内部this指向window,最后输出window.id
    */

    其实有一些调用其根本原因是相同的,但是我个人喜欢各个方面去验证一下,加深一下印象也好,勿喷
    附带说一嘴,如果有同学在学node, node内部是没有window对象的,window是浏览器规范,所以具体情况看你在哪里用了,不过概念是差不多的

    写完觉得这篇文章真的是浅谈...好low啊哈哈哈哈,写给自己看!

  • 相关阅读:
    iOS 获取手机当前所连接的网络的IP地址
    np.delete详解
    np.concatenate函数
    说说如何在 Python 中使用日志
    Python os.getcwd() 方法
    python的构造函数
    python引入自己写的Py文件
    VS CODE编译Python输出中文乱码
    VScode中pytorch出现Module 'torch' has no 'xx' member错误
    matlab处理hd5高维数据
  • 原文地址:https://www.cnblogs.com/jeodeng/p/10658590.html
Copyright © 2011-2022 走看看