资讯专栏INFORMATION COLUMN

ES6箭头函数体中this指向哪里?

Half / 1093人阅读

摘要:注意因为箭头函数内部的是指向外层代码块的最近的,例中的函数的,所以我们可以通过改变外层代码块的的指向从而改变箭头函数中的指向例中使用了函数的方法。

一、this关键字小测试
ES6箭头函数体中的this指向哪里?

在回答这个问题之前先来揣揣你对this关键字的了解程度:
(让我们回到ES6之前)
题:

var obj = {
    a: function() {
        console.log(this);
    }
}

var b = obj.a;
b();

问:打印出的this的值?
再来几个选项:

window

obj

document

obj.a

答案是window(可以在控制台运行一下)

什么!什么情况!发生了什么?

一句话解释:
一般的,this指向函数运行(调用)时所在的执行环境【《JavaScript高级程序设计》4.2节执行环境及作用域】的(变量)对象(简单地,this指向函数的调用者)

分析代码:

var b = obj.a;    // ==>相当于
var b = function() {
    console.log(this);
}

函数调用时(b();)其所在的执行环境是全局环境,所以this指向全局变量对象window

二、ES6箭头函数
如果你觉得以上这些都知道了(我会!我会!)那么就继续吧~~

(来到ES6箭头函数)

例1【阮一峰《ECMAScript 6 入门》-7.函数的扩展:箭头函数】

我将阮老师的例子代码修改了一下:
(普通函数)

function foo() {
    console.log("id1:", this.id);
    console.log("this1:", this);
    setTimeout(function() {
        console.log("id2:", this.id);
        console.log("this2:", this);
    }, 0);
}

var id = 21;

foo();

// Chrome
// id1: 21
// this1: window
// id2: 21
// this2: window

foo.call({id: 42});

// Chrome
// id1: 42
// this1: {id: 42}
// id2: 21
// this2: window

注意:超时调用(setTimeout回调)的代码都是在全局作用域环境中执行的,因此(setTimeout回调)函数中this的值在非严格模式下指向window对象,在严格模式下是undefined

例如

var obj = {
    console.log(this);
    setTimeout(function() {
        console.log(this);
    }, 0);
}

obj.a();

// Chrome
// {a: f}
// window
回到例1

我们使用foo函数的call方法改变了foo函数调用时函数体内this的指向({id: 42}这个对象),但setTimeout回调函数中的this依旧指向window对象(因为在全局环境中运行)。

接下来再将例1改写一下,将foo函数中的setTimeout回调函数改成箭头函数的形式:

例2
(箭头函数)

function foo() {
    console.log("id1:", this.id);
    console.log("this1:", this);
    setTimeout(() => {
        console.log("id2:", this.id);
        console.log("this2:", this);
    }, 0);
}

var id = 21;

foo();

// Chrome
// id1: 21
// this1: window
// id2: 21
// this2: window

foo.call({id: 42});

// Chrome
// id1: 42
// this1: {id: 42}
// id2: 42
// this2: {id: 42}

foo();的输出结果没有变化,但foo.call({id: 42});的输出结果改变了。

到底发生了什么?

在这里直接给出结论:
箭头函数根本没有自己的this,导致内部的this指向了外层代码的this这个指向在定义时就已经确定而不会在调用时指向其执行环境的(变量)对象

注意:因为箭头函数内部的this是指向外层代码块的this(最近的this,例2中的foo函数)的,所以我们可以通过改变外层代码块的this的指向从而改变箭头函数中this的指向(例2中使用了foo函数的call方法)。

重新解释例2

因为箭头函数(setTimeout回调)没有自己的this,导致其内部的this引用了外层代码块的this,即foo函数的this

(要注意:在定义阶段(调用函数前),foo函数的this的值并不确定【《JavaScript高级程序设计》第三版5.5.4函数内部属性】,但箭头函数的this自定义阶段开始就指向foo函数的this了)

又因为使用call方法改变了foo函数运行(调用)时其函数体内this的指向(重新指向对象{id: 42})从而使箭头函数中this的指向发生变化,最后输出例2所示结果。

三、例子总结

到这里,我想小伙伴们应该是比较清楚了,那么不妨去看看阮一峰老师的《ECMAScript 6 入门》函数的扩展一节箭头函数部分的一个问题示例:“请问下面的代码中有几个this(滑稽)”

加深印象

例3【阮一峰《ECMAScript 6 入门》-19.Class基本语法:this的指向】

class Logger {
  constructor() {
    this.printName = (name = "there") => {
      this.print(`Hello ${name}`);
    };
  }

  // ...
}

箭头函数中的this指向constructor构造方法内部的this,由于此时constructor中的this尚未获得值,当通过new命令生成对象实例时,将会自动调用constructor方法,constructorthis才能指向该实例对象,在此过程中,箭头函数中的this一直引用着constructor中的this,当constructorthis发生变化,箭头函数的this也会一并发生变化。

若有错误,请指出批评!!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93762.html

相关文章

  • ES6精华:函数扩展

    摘要:在函数方面的扩展比较丰富也很实用,本篇概括了这中的精华知识。所以无法成为构造函数,不能使用操作符。参数将扩展运算符作用于参数,即为参数。声明式,直接为函数名。通过构造函数生成的,为。函数的属性,在其描述对象的属性上,为函数名。 ES6在函数方面的扩展比较丰富也很实用,本篇概括了这中的精华知识。 1 箭头函数 箭头函数是ES6中定义函数的新形式。 新形式不仅简化了定义方式,更为函数本身...

    lansheng228 评论0 收藏0
  • ES6系列】函数部分

    摘要:正是因为它没有,所以也就不能用作构造函数。不可以当作构造函数,也就是说,不可以使用命令,否则会抛出一个错误。不可以使用对象,该对象在函数体内不存在。 箭头函数 在之前ES5的版本中,我们定义一个函数的形式如下: function a() { // do something…… } 但是在ES6中,则新增了箭头函数的方式,ES6中允许使用箭头(=>)来定义函数。 () => { ...

    enda 评论0 收藏0
  • 从-1开始的ES6探索之旅01:颜文字成精的箭头函数 上篇 - 大哥,你指哪呢?

    摘要:基础语法参数参数参数函数声明参数参数参数表达式单一相当于参数参数参数表达式当只有一个参数时,圆括号是可选的单一参数函数声明单一参数函数声明没有参数的函数应该写成一对圆括号。 温馨提示:作者的爬坑记录,对你等大神完全没有价值,别在我这浪费生命温馨提示-续:你们要非得看,我也拦不住,但是至少得准备个支持ES6的Chrome浏览器吧? 之前在某些大神的代码中出现一串神秘符号类似于num =>...

    Snailclimb 评论0 收藏0
  • 论普通函数箭头函数的区别以及箭头函数的注意事项、不适用场景

    摘要:第二种情况是箭头函数的如果指向普通函数它的继承于该普通函数。箭头函数的指向全局,使用会报未声明的错误。 showImg(https://segmentfault.com/img/remote/1460000018610072?w=600&h=400); 箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API...

    paulquei 评论0 收藏0
  • 关于ES6箭头函数this问题

    摘要:对象的指向是可变的,但是在箭头函数中,它是固定的。同样的由于箭头函数没有自己的所以传统的显性绑定无效内部的指向外部在的学习中,的指向问题一直是个难点,特别是在对象方法中使用时,必须更加小心。由此箭头函数在很大程度上减少了我们的困扰。 什么是箭头函数 用法 ES6 允许使用箭头(=>)定义函数 测试 var p1 = document.getElementById(test1)...

    LeviDing 评论0 收藏0

发表评论

0条评论

Half

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<