ES6中的箭头函数中的“ this”指的是什么?

我在几个地方读到,关键区别在于 this在词法上绑定在箭头函数中。那很好,但我不知道那是什么意思。

我知道这意味着它在定义函数体的大括号的范围内是唯一的,但我实际上不能告诉你下面代码的输出,因为我不知道 this指的是什么,除非它指的是脂肪箭头函数本身... ... 这似乎没什么用。

var testFunction = () => {
console.log(this)
};
testFunction();

20522 次浏览

箭头函数捕获封闭上下文的 this

function Person(){
this.age = 0;


setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}


var p = new Person();

所以,为了直接回答你的问题,你的箭头函数中的 this值应该和指定箭头函数之前的值相同。

希望这个代码展示可以让您有更清晰的认识。基本上,箭头函数中的‘ this’是‘ this’的当前上下文版本。查看代码:

// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window

为了提供更全面的信息,我将同时解释动态绑定和词汇绑定。

动态名称绑定

this引用调用该方法的对象。这是一个定期阅读的句子。但它仍然只是一个短语,相当抽象。这个句子有对应的代码模式吗?

是的:

const o = {
m() { console.log(this) }
}


// the important patterns: applying methods


o.m(); // logs o
o["m"](); // logs o

m是一种方法,因为它依赖于 thiso.m()o["m"]()意味着 m适用于 o。这些模式是我们著名短语的 Javascript 翻译。

还有一个重要的代码模式需要注意:

"use strict";


const o = {
m() { console.log(this) }
}


// m is passed to f as a callback
function f(m) { m() }


// another important pattern: passing methods


f(o.m); // logs undefined
f(o["m"]); // logs undefined

它与前面的模式非常相似,只是缺少括号。但是结果是相当可观的: 当您将 m传递给函数 f时,您将取出它的对象/上下文 om。它现在被连根拔起,而且 this没有任何参考(严格模式假设)。

词法(或静态)名称绑定

箭头函数没有自己的 this/super/arguments绑定,它们从父词法作用域继承它们:

const toString = Object.prototype.toString;


const o = {
foo: () => console.log("window", toString.call(this)),
      

bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}


o.foo() // logs window [object Window]
o.bar() // logs o [object Object]

除了全局作用域(浏览器中的 Window)之外,只有函数能够在 Javascript 中形成作用域(ES2015中的 {}块)。当调用 o.foo箭头函数时,没有一个周围的函数可以让 baz继承它的 this。因此,它捕获绑定到 Window对象的全局范围的 this绑定。

o.bar调用 baz时,箭头函数被 o.bar包围(o.bar形成其父词法范围) ,并且可以继承 o.barthis绑定。o.baro上被调用,因此它的 this被绑定到 o上。

你可以按照下面的方法来理解它

// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}

所以“ this”在胖箭头函数中是没有绑定的,这意味着你不能让任何东西绑定到这里的“ this”。申请不会。打不了电话。绑定不会。当您在文本编辑器中写下代码文本时,胖箭头函数中的“ this”将被绑定.“ this”在胖箭头函数中的字面意义。您的代码在文本编辑器中编写的内容就是您的应用程序在 repl 中运行的内容。除非在文本编辑器中进行更改,否则在胖错误中绑定的‘ this’永远不会改变. 对不起,我的台球英语..。

箭头函数 this指向 ES6中的周围父函数,这意味着它的作用域不像 ES5中的匿名函数..。

这是一种非常有效的方法,避免了在 ES5中广泛使用的赋值方法。

看下面的例子,在一个对象中赋值一个函数:

var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};


checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}

在另一个示例中,如果单击下面的年龄按钮

<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};


var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};


</script>






<input type=button onClick="alert(person2.age());" value="Age">

它会抛出这样的异常

× JavaScript 错误: 未捕获的 TypeError: 无法读取属性 第18行中未定义的‘ getFullYear’

但是如果你换了人,这条线

return new Date().getFullYear() - this.dob.getFullYear();

return new Date().getFullYear() - person2.dob.getFullYear();

它将工作,因为这个范围已经在人2中发生了变化

箭头函数从不与 this关键字绑定

var env = "globalOutside";
var checkThis = {env: "insideNewObject", arrowFunc: () => {
console.log("environment: ", this.env);
} }


checkThis.arrowFunc()   // expected answer is environment: globalOutside


// Now General function
var env = "globalOutside";
var checkThis = {env: "insideNewObject", generalFunc: function() {
console.log("environment: ", this.env);
} }
checkThis.generalFunc() // expected answer is enviroment: insideNewObject


// Hence proving that arrow function never binds with 'this'

在箭头函数中使用时,这个 将始终引用全局对象。使用常规函数声明引用本地对象。此外,您可以使用对象名作为上下文(object.method,而不是 this.method) ,以便它引用本地对象而不是全局对象(窗口)。

箭头函数与常规函数之间的差异: (取自 W3学校)

对于箭头函数,这个函数没有绑定。

在常规函数中,this 关键字表示调用函数的对象,函数可以是窗口、文档、按钮或其他。

在箭头函数中,this 关键字始终表示定义箭头函数的对象。

// Regular Function:
hello = function() {
document.getElementById("demo").innerHTML += this;
}


// The window object calls the function:
window.addEventListener("load", hello);


// A button object calls the function:
document.getElementById("btn").addEventListener("click", hello);


// -------------------------------------------


// Arrow function
hello2 = () => {
document.getElementById("demo2").innerHTML += this;
}


// The window object calls the function:
window.addEventListener("load", hello2);


// A button object calls the function:
document.getElementById("btn2").addEventListener("click", hello2);
<p><i>With a regular function this represents the <b>object that calls the function</b>:</i></p>


<button id='btn'>click me regular function</button>


<p id="demo">Regular function: </p>


<hr>


<p><i>With arrow function this represents the <b>owner of the function(=the window object)</b>:</i></p>


<button id='btn2'>click me arrow function</button>


<p id="demo2">Arrow function: </p>

一个相关问题:

来自 为什么我不能在一个箭头函数中访问‘ this’?

我们从这里知道: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

没有它自己对这个 或 super 的绑定,因此不应该用作方法。

箭头函数基于 作用域中定义了 Arrow 函数建立“ this”。

在使用箭头函数时遇到了 this的问题,因此创建了一个类(可以是函数) ,并且类变量在箭头函数中被访问,从而在没有使用 function关键字的情况下使用箭头函数实现了更小的函数:

class MyClassOrFunction {
values = [];
size = () => this.values.length;
isEmpty = () => this.size() === 0;
}


let obj = new MyClassOrFunction();
obj.size(); // function call here

你也可以有一个像这样的 getter,它没有 function关键字,但是由于 return语句的原因稍微长了一点,还可以访问其他成员函数:

class MyClassOrFunction {
values = [];
size = () => this.values.length;
get length() {  return this.size();  }
}
let obj = new MyClassOrFunction();
obj.length; // NOTE: no function call here