声明:本文转载自 https://blog.csdn.net/yangbingbinga/article/details/61424363

ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取this的特性,俘获了大批粉丝儿

它也可能是面试中的宠儿, 我们关键要搞清楚 箭头函数和普通函数中的this

一针见血式总结:

普通函数中的this:

1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj

2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (约定俗成)

3.在严格模式下,没有直接调用者的函数中的this是 undefined

4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象

箭头函数中的this

箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this

下面通过一些例子来研究一下 this的一些使用场景[ 使用最新版 chrome测试 ]

要整明白这些, 我们需要首先了解一下作用域链:

当在函数中使用一个变量的时候,首先在本函数内部查找该变量,如果找不到则找其父级函数,

最后直到window,全局变量默认挂载在window对象下

1.全局变量默认挂载在window对象下


  1. <script>
  2.  var aa = 2;
  3.  alert(window.aa);
  4.  (function () {
  5.    aa = 3;
  6.  })();
  7.  alert(window.aa);
  8. </script>

我们仅仅声明了一个全局变量aa,但是打印出window.aa却和aa保持一致,为什么呢?

眼见为实, 我们使用console.dir(window) 打印 window对象看看

我们可以看到在window属性中,看到 aa 属性了;此外,函数也适用于此情况,全局函数也会挂在在window对象下

我们常见的window的属性和方法有: alert, location,document,parseInt,setTimeout,setInterval等,window的属性默认可以省略window前缀!

2.在普通函数中,this指向它的直接调用者;如果找不到直接调用者,则是window

我们来看一些例子

示例1:


  1. <script>
  2.  function test() {
  3.    console.log(this);
  4.  }
  5.  test();
  6. </script>

结果是: window

原因: test()是一个全局函数,也就是说是挂在window对象下的,所以test()等价于 window.test() ,所以此时的this是window

示例2:


  1. <script>
  2.  var obj = {
  3.    say: function () {
  4.      setTimeout(function () {
  5.        console.log(this)
  6.      });
  7.    }
  8.  }
  9.  obj.say();
  10. </script>

结果是: window

匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window

问题: 如果想要在setTimeout/setInterval中使用这个对象的this引用呢?

用一个 变量提前把正确的 this引用保存 起来, 我们通常使用that = this, 或者 _this = this来保存我们需要的this指针!


  1. <script>
  2.  var obj = {
  3.    func: function() {},
  4.    say: function () {
  5.      var that = this;   //此时的this就是obj对象
  6.      setTimeout(function () {
  7.        console.log(this)
  8.        that.func()
  9.      });
  10.    }
  11.  }
  12.  obj.say();
  13. </script>

我们也可以使用 func.bind(this) 给回调函数直接绑定宿主对象, bind绑定宿主对象后依然返回这个函数, 这是更优雅的做法

  1. <span style="font-family:'Times New Roman';"><script>
  2. var obj = {
  3. func: function() {},
  4. say: function () {
  5. // 此时的this就是obj对象
  6. setTimeout(function () {
  7. console.log(this)
  8. this.func()
  9. }.bind(this));
  10. }
  11. }
  12. obj.say(); // obj
  13. </script></span>

示例3(改变自360面试题):


  1.  window.val = 1;
  2.  var obj = {
  3.    val: 2,
  4.    dbl: function () {
  5.      this.val *= 2;
  6.      val *= 2;
  7.      console.log(val);
  8.      console.log(this.val);
  9.    }
  10.  };
  11.  // 说出下面的输出结果
  12.  obj.dbl();
  13.  var func = obj.dbl;
  14.  func();

结果是:  2   4    8   8

<1> 12行代码调用

val变量在没有指定对象前缀,默认从函数中找,找不到则从window中找全局变量

即 val *=2 就是 window.val *= 2

this.val默认指的是 obj.val ;因为 dbl()第一次被obj直接调用

<2>14行代码调用

func() 没有任何前缀,类似于全局函数,即  window.func调用,所以

第二次调用的时候, this指的是window, val指的是window.val

第二次的结果受第一次的影响

3.在严格模式下的this


  1. <script>
  2.  function test() {
  3.    'use strict';
  4.    console.log(this);
  5.  }
  6.  test();
  7. </script>

结果是: undefined

4.箭头函数中的 this


  1. <script>
  2.  var obj = {
  3.    say: function () {
  4.      setTimeout(() => {
  5.        console.log(this)
  6.      });
  7.    }
  8.  }
  9.  obj.say(); // obj
  10. </script>

此时的 this继承自obj, 指的是定义它的对象obj, 而不是 window!

示例(多层嵌套的箭头函数):


  1. <script>
  2. var obj = {
  3. say: function () {
  4.   var f1 = () => {
  5.     console.log(this); // obj
  6.     setTimeout(() => {
  7.       console.log(this); // obj
  8.     })
  9.   }
  10.   f1();
  11.   }
  12. }
  13. obj.say()
  14. </script>

因为f1定义时所处的函数 中的 this是指的 obj, setTimeout中的箭头函数this继承自f1, 所以不管有多层嵌套,都是 obj

示例(复杂情况: 普通函数和箭头函数混杂嵌套)


  1. <script>
  2. var obj = {
  3. say: function () {
  4.   var f1 = function () {
  5.     console.log(this); // window, f1调用时,没有宿主对象,默认是window
  6.     setTimeout(() => {
  7.       console.log(this); // window
  8.     })
  9.   };
  10.   f1();
  11.   }
  12. }
  13. obj.say()
  14. </script>
结果: 都是 window,因为 箭头函数在定义的时候它所处的环境相当于是window, 所以在箭头函数内部的this函数window

示例(严格模式下的混杂嵌套)


  1. <script>
  2. var obj = {
  3. say: function () {
  4.   'use strict';
  5.   var f1 = function () {
  6.   console.log(this); // undefined
  7.   setTimeout(() => {
  8.     console.log(this); // undefined
  9.   })
  10.   };
  11.   f1();
  12.  }
  13. }
  14. obj.say()
  15. </script>

结果都是undefined

说明: 严格模式下,没有宿主调用的函数中的this是undefined!!!所以箭头函数中的也是undefined!

总结:

使用箭头函数,可以让我们解决一些在匿名函数中 this指向不正确的问题; 但是要注意在和普通函数混合的时候,this的指向可能是window !

Y(^o^)Y, 掌握这么多已经足够面试绝大部分关于this的内容了,我们在开发中的应用也没问题了!

如果对大家有所帮助, 我会感到很开心!

(转载) 深入理解ES6箭头函数的this以及各类this面试题总结的更多相关文章

  1. 深入理解ES6箭头函数的this以及各类this面试题总结

    ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取this的特性,俘获了大批粉丝儿 它也可能是面试中的宠儿, 我们关键要搞清楚 箭头函数和普通函数中的this 一针见血式总结: 普通函数中的 ...

  2. 深入理解ES6箭头函数中的this

    简要介绍:箭头函数中的this,指向与一般function定义的函数不同,比较容易绕晕,箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定. 1.何为定义时 ...

  3. 理解es6箭头函数

    箭头函数知识点很少,但是要理解清楚,不然看代码会很不适应的. 1. 最简单的写法 x => x*x 可以理解为 我的x要被转化为x*x,所以实际相当于下边的这个 function (x){ re ...

  4. es6箭头函数 this 指向问题

    es5中 this 的指向 var factory = function(){ this.a = 'a'; this.b = 'b'; this.c = { a:'a+', b:function(){ ...

  5. ES6 — 箭头函数

    一 为什么要有箭头函数 我们在日常开发中,可能会需要写类似下面的代码 const Person = { 'name': 'little bear', 'age': 18, 'sayHello': fu ...

  6. 前端分享----JS异步编程+ES6箭头函数

    前端分享----JS异步编程+ES6箭头函数 ##概述Javascript语言的执行环境是"单线程"(single thread).所谓"单线程",就是指一次只 ...

  7. this(ES6箭头函数里的this)

    一,了解前须知 1,箭头函数:出现的作用除了让函数的书写变得很简洁,可读性很好外:最大的优点是解决了this执行环境所造成的一些问题.比如:解决了匿名函数this指向的问题(匿名函数的执行环境具有全局 ...

  8. ES6 箭头函数你正确使用了吗

    ES6 箭头函数你正确使用了吗 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 说明 在ES6中允许使用"箭头&quo ...

  9. es6箭头函数讲解

    es6箭头函数的用法 箭头函数是es6的一种函数的简写方法. 如下: var f = v = > v; //等同于 var f = function(v){ return v; } var su ...

随机推荐

  1. 大数据学习之BigData常用算法和数据结构

    大数据学习之BigData常用算法和数据结构 1.Bloom Filter     由一个很长的二进制向量和一系列hash函数组成     优点:可以减少IO操作,省空间     缺点:不支持删除,有 ...

  2. ES6数组中删除指定元素

    知识点: ES6从数组中删除指定元素 findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引.否则返回-1. arr.splice(arr.findIndex(item => ...

  3. JS对象中属性的增删改查

    对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性 对象的分类:           1.内建对象                 -在ES标准中定义的对象,在任何的ES的实现中都可以 ...

  4. vue/cli3引入cesium

    vue/cli3引入cesium 一开始用了webpack结合vue引入vue:结果是各种bug,搞了半天.最后问了基友,发现vue脚手架这个·简单高效的方法,只需要几行代码就轻松地搞定啦! 方案一. ...

  5. 使用正则限制input框只能输入数字/英文/中文等等

    常用HTML正则表达式 1.只能输入数字和英文的: 复制代码代码如下: <input onkeyup="value=value.replace(/[/W]/g,'') " o ...

  6. Java 13 即将发布,新特性必须抢先看!

    作者:h4cd 本文转载自开源中国(ID:oschina2013) 由于 Java 现在采取"半年发布一次新版本"的模式,所以 Java 12 的下一个版本 Java 13/JDK ...

  7. NFS挂载error:reason given by server: Permission denied

    首先你得看看你的NFS服务有没有启动 然后你看看你要mount的文件夹有没有在NFS主机共享 然后再看权限对没对

  8. OI中的快速傅里叶变换(FFT)

    快速傅里叶变换(FFT)                                                                               ---- LLpp ...

  9. Javascript高级程序设计--读书笔记之面向对象(二)

    前面讲了面向对象的封装,这章我们就来说一说继承 1.原型链 实现原型链有一种基本模式,其代码大概如下 <script> function SuperType(){ this.propert ...

  10. 【教程】CentOS 7安装 最新版本Docker

    博主最近需要安装Docker,步骤如下: Docker安装官方地址:https://docs.docker.com/install/linux/docker-ce/centos/ 以下命令都是在roo ...