声明:本文转载自 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.  
  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.  
  1. <script>
  2.  function test() {
  3.    console.log(this);
  4.  }
  5.  test();
  6. </script>

结果是: window

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

示例2:

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

结果是: undefined

4.箭头函数中的 this

  1.  
  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.  
  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.  
  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.  
  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. 97、PageRank算法学习

    最近由于.......你懂得,需要一些搜索方面的知识,于是乎我重新复习了一下上半年读的那本书<数学之美>Dr吴军老师写的. 感觉读完这种书还是写一下比较好,因为将来说不定就会忘记了. 接下 ...

  2. 01java基础笔记

    计算机组成:运算器,控制器,存储器,输入输出设备(外部设备I/O设备) 机器语言:机器语言,汇编语言,高级语言 人机交互:命令行方式,图形化界面交互方式 JAVA语言平台分为:J2SE,J2ME,J2 ...

  3. HDU1251-统计难题-map+输入

    Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input输入数据的第一部分 ...

  4. 在VMware下创建windows2008虚拟机

    1.创建新的虚拟机 打开VMware软件,点击主页内创建新的虚拟机 2.进入新建虚拟机向导 点击典型,点击下一步 3.在下一步中单击稍后安装操作系统 点击下一步 4.选择操作系统类型 客户机操作系统选 ...

  5. java 并发——CountDownLatch

    java 并发--CountDownLatch 简介 public class CountDownLatch { private final Sync sync; private static fin ...

  6. Shell判断某文件夹下是否存在xxx开头的字符串

    Usage: bash judge_prefix_string.sh TARGET_DIR TARGET_STR #!/bin/bash TARGET_DIR=$1 TARGET_STR=$2 ls ...

  7. C# 线程池的使用 终止线程池中的队列

    C#的线程池使用起来还是非常简单的,这里记录一下. 根据http://blog.csdn.net/chen_zw/article/details/7939834里的描述这里记录一下C#线程池的特点 一 ...

  8. Oracle多种表连接方式

    1. 内连接(自然连接) 2. 外连接 (1)左外连接 (左边的表不加限制) (2)右外连接(右边的表不加限制) (3)全外连接(左右两表都不加限制) 3. 自连接(同一张表内的连接) SQL的标准语 ...

  9. centos7 实测 nagios 安装

    Nagios是一套开源的监控系统,可监控你的系统和网络.Nagios最新版本是Nagios Core 4.3.4,Nagios plugins 2.2.1.目前支持RHEL 7.x/6.x/5.x, ...

  10. Eclipse导入的Maven项目没有Build Path

    我导入的是 Signal-Server项目到 Eclipse中,发现 src 文件夹上面没有#号,包视图和语法提示都没有 ~~ 解决方法: 修改 Project Facets 在 项目右键 -> ...