this指向本质

箭头函数this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

箭头函数转成 ES5 的代码如下:

// ES6
function foo() {
setTimeout(() => {
console.log('id:', this.id);
}, 100);
} // ES5
function foo() {
var _this = this; setTimeout(function () {
console.log('id:', _this.id);
}, 100);
}

this指向实例

实例1

下面代码中,setTimeout的参数是一个箭头函数,这个箭头函数的定义生效是在foo函数生成时,而它的真正执行要等到100毫秒后。如果是普通函数,执行时this应该指向全局对象window,这时应该输出21。但是,箭头函数导致this总是指向函数定义生效时所在的对象(本例是{id: 42}),所以输出的是42。

function foo() {
console.log(this); // { id: 42 }
setTimeout(() => {
//箭头函数体中的 this 对象,是定义函数时的对象,而不是使用函数时的对象。
console.log('id:', this.id); // 42
}, 100);
}
var id = 21;
foo.call({ id: 42 }); // id: 42

实例2

ES5没有块级作用域【对象、if、for、while不构成单独的作用域】,其只有全局作用域和函数作用域,所以函数b()定义时的作用域就是全局作用域

var obj = {
a: 10,
b: () => {
console.log(this.a); // undefined
console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
},
c: function() {
console.log(this.a); // 10
console.log(this); // {a: 10, b: ƒ, c: ƒ}
}
}
obj.b();
obj.c();

实例3

实例1和实例2的组合加强版

var obj = {
a: 10,
b: () => {
console.log(this) // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
setTimeout(() => {
console.log(this.a) // undefined
console.log(this)// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
});
},
c: function() {
console.log(this) // {a: 10, b: ƒ, c: ƒ}
setTimeout(() => {
console.log(this.a) // 10
console.log(this) // {a: 10, b: ƒ, c: ƒ}
});
},
d: function() {
console.log(this) // {a: 10, b: ƒ, c: ƒ}
setTimeout(function(){
console.log(this.a) // undefined
console.log(this)// Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
});
}
}
obj.b();
obj.c();
obj.d();

不适用场合

定义对象的方法,且该方法内部包括this

const cat = {
lives: 9,
jumps: () => {
this.lives--;
}
}

上面代码中,cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps()时,如果是普通函数,该方法内部的this指向cat;如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。

注意点

  • 箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
  • 不可以使用yield命令,因此箭头函数不能用作Generator函数。

参考文档

阮一峰 函数的扩展

箭头函数this指向问题的更多相关文章

  1. ES6 箭头函数 this 指向

    ES6 箭头函数 this 指向 箭头函数有几个使用注意点: 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个 ...

  2. ES6 箭头函数this指向问题

    var name = "window"; var person1 = { name: "person1", show1: function() { consol ...

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

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

  4. 5. 箭头函数_this 指向_es6 常用语法

    1. 箭头函数 函数的简写方式 () => {} 只有一个参数时,可以省略() ---- x => {} 只有一条语句时,可以省略{},此时这点语句的结果会作为函数的返回值返回  () = ...

  5. typescript 属性默认值使用箭头函数 this指向问题

    今天注意到前端小伙伴用react 定义component class的方法的时候是通过箭头函数的方式,表示好奇. class Test extends React.Component { public ...

  6. ES6箭头函数this指向

    普通函数中的this: 1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj 2.在默认情况(非严格模式下,未使用 'us ...

  7. 箭头函数中可改变this作用域,回调函数用箭头函数this指向page,自定义事件用箭头函数this指向undefined

    1.回调函数中,用箭头函数改变this的作用域 success: (res)=>{ this.setData({ //此时,this指向page页面 ... }) } 2.自定义事件中,如果使用 ...

  8. js中箭头函数 及 针对箭头函数this指向问题引出的单体模式

    ES6允许使用“箭头”(=>)定义函数 var f = a = > a //等同于 var f = function(a){ return a; } 如果箭头函数不需要参数或需要多个参数, ...

  9. ES6 箭头函数this指向

    箭头函数有几个使用注意点. (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象. (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误. (3)不可以使 ...

随机推荐

  1. mysql 常用命令和笔记

    第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...

  2. 储存与RAID--独立磁盘阵列

    存储:  专门用来插硬盘的机器,作用是增加插口,可以多插硬盘. 这种有策略保证硬盘坏了,数据不丢.而本地磁盘坏了,会导致数据丢失,故一般操作系统放在本地磁盘.而数据放在存储盘. 存储里依然有:cpu( ...

  3. rbd-mirror配置指南-单向备份

    前言 RBD 的 mirroring 功能将在Jewel中实现的,这个Jewel版本已经发布了很久了,这个功能已经在这个发布的版本中实现了,本来之前写过一篇文章,但是有几个朋友根据文档配置后,发现还是 ...

  4. mysql之事物

    1.事物,在事物中的sql语句,要么全部执行成功,要么全部执行失败,不会出现一条sql执行成功了,一条sql执行失败的问题. 2.开启事物:就是关闭mysql自己的自动提交事物的方式 3.commit ...

  5. 《Machine Learning in Action》—— 小朋友,快来玩啊,决策树呦

    <Machine Learning in Action>-- 小朋友,快来玩啊,决策树呦 在上篇文章中,<Machine Learning in Action>-- Taoye ...

  6. MathType如何打出带圆圈的点

    学习了圆的知识后,知道可以用带圆圈的点表示圆,比如"⊙O"表示圆O,即圆心为O的圆.那么要怎么在MathType中打出带圆圈的点? 方法一.直接在工具栏上选择输入 打开MathTy ...

  7. Flink-1-状态化流处理概述

    第1章 状态化流处理概述 参考书籍 Stream Processing with Apache Flinkhttps://www.oreilly.com/library/view/stream-pro ...

  8. 【Luogu U41492】树上数颜色——树上启发式合并(dsu on tree)

    (这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下 ...

  9. Matlab 条件循环函数

    条件判断 if 表达式 语句 elseif 表达式 语句 -. else 语句 end 这个与c语言不同的就是 1:要多一个end 2:还有没有括号 3:else if连在一起 for 循环 for ...

  10. 程序演示:C语言第一个简单实例

    在信息化.智能化的世界里,可能很早很早 我们就听过许多IT类的名词,C语言也在其中,我们侃侃而谈,到底C程序是什么样子?让我们先看简单的一个例子: 1 2 3 4 5 6 7 8 9 #include ...