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绑定宿主对象后依然返回这个函数, 这是更优雅的做法

示例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面试题总结

    声明:本文转载自 https://blog.csdn.net/yangbingbinga/article/details/61424363 ES6中新增了箭头函数这种语法,箭头函数以其简洁性和方便获取 ...

  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. plsql developer 执行sql 文件

    用 Command Window,执行 @'sql file path' 注意,上面sql文件路径要加单引号

  2. 双系统更新ubuntu后,启动引导项消失,无法进入windows

    1.打开终端输入命令sudo gedit /etc/default/grub 2.修改GRUB_TIMEOUT="10" 3.输入sudo update-grub( update ...

  3. C# 多线程程序隐患

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. HTTP协议初识

    HTTP协议介绍 当你在浏览器地址栏敲入“http://www.cnblogs.com/”,然后猛按回车,呈现在你面前的,将是博客园的首页了(这真是废话,你会认为这是理所当然的).作为一个开发者,尤其 ...

  5. python进阶11 正则表达式

    python进阶11 正则表达式 一.概念 #正则表达式主要解决什么问题? #1.判断一个字符串是否匹配给定的格式,判断用户提交的又想的格式是否正确 #2.从一个字符串中按指定格式提取信息,抓取页面中 ...

  6. 浅谈最近公共祖先(LCA)

    LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. (来自百度百科) 一.倍增求LCA 预处理出距点u距离为2^0,2^1,2 ...

  7. 牛客网Java刷题知识点之关键字static、static成员变量、static成员方法、static代码块和static内部类

    不多说,直接上干货! 牛客网Java刷题知识点之关键字static static代表着什么 在Java中并不存在全局变量的概念,但是我们可以通过static来实现一个“伪全局”的概念,在Java中st ...

  8. Git 忽略規則及 .gitignore 規則不生效的辦法

    Git忽略规则: 在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如果没有这个文件,则需自己手工建立此文件).这个文件每一行保存了一 ...

  9. Random类、ThreadLocalRandom类

    Random和ThreadLocalRandom类均用于生成伪随机数. Random的构造函数: Random()     默认以系统当前时间为种子,相当于Random(System.currentT ...

  10. Mysql order by 排序 varchar 类型数据

    Mysql order by 排序 varchar 类型数据 varchar 类型字段排序,  会將数字当成字符串来处理.  排序规则一般是从左到右一位位来比较. +0之后 就转化成INT 类型排序 ...