ES6 中的箭头函数中的“this”指的是啥?
Posted
技术标签:
【中文标题】ES6 中的箭头函数中的“this”指的是啥?【英文标题】:What does "this" refer to in arrow functions in ES6?ES6 中的箭头函数中的“this”指的是什么? 【发布时间】:2022-01-14 06:07:35 【问题描述】:我在几个地方读到,主要区别在于 this
在词法上绑定在箭头函数中。这一切都很好,但我实际上并不知道这意味着什么。
我知道这意味着它在定义函数体的大括号范围内是唯一的,但我实际上无法告诉您以下代码的输出,因为我不知道 this
指的是什么,除非它是指的是胖箭头函数本身......这似乎没有用。
var testFunction = () => console.log(this) ;
testFunction();
【问题讨论】:
它只是从包含范围内捕获this
的值,将其视为任何其他变量。
这样您就不必在函数中使用var self = this;
的kludge。
在您的情况下,没有封闭上下文,或者它是全局上下文或模块上下文,所以 this
在这种情况下是什么,很可能是 null 或 window.context。换句话说,this
的值与在函数赋值之前添加console.log(this)
的值完全相同。
【参考方案1】:
Arrow functions capture the this
value of the enclosing context
function Person()
this.age = 0;
setInterval(() =>
this.age++; // |this| properly refers to the person object
, 1000);
var p = new Person();
因此,直接回答您的问题,箭头函数内的this
将具有与分配箭头函数之前相同的值。
【讨论】:
@torazaburo 迟来的回应——答案是它取决于原始问题中代码 sn-p 的位置。如果它在顶层,如果我们在浏览器中,this
是 window
对象,如果我们在 Node 环境中,module.exports
是对象。重点是,箭头函数对this
的值没有影响。【参考方案2】:
为了提供全局,我将解释动态绑定和词法绑定。
动态名称绑定
this
指的是调用该方法的对象。这是关于 SO 的一个经常阅读的句子。但它仍然只是一个短语,相当抽象。这句话有对应的码型吗?
是的,有:
const o =
m() console.log(this)
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m
是一种方法,因为它依赖于this
。 o.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
时,你会拉出它的对象/上下文o
的m
。它现在被连根拔起,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
绑定。
当baz
被o.bar
调用时,箭头函数被o.bar
包围(o.bar
形成它的父词法作用域)并且可以继承o.bar
的this
绑定。 o.bar
在 o
上被调用,因此它的 this
绑定到 o
。
【讨论】:
你能帮帮我吗,为什么没有严格模式,它记录窗口,但使用严格模式,它记录未定义?这是严格模式的哪个属性?【参考方案3】:希望这个代码展示能给你更清晰的想法。基本上,箭头函数中的“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
【讨论】:
非常简短和很好的例子。当使用function
时,this
值是在调用/调用函数时创建的。因此,当您将其称为this1.logFunction()
时,您将其称为对象this1
的方法,而this
指的是this1 文字对象。另一方面,如果使用箭头函数,this
值不会根据调用/调用方式创建,而是从词法范围继承,在本例中为 window
object,其中定义了 this1 obejct。
【参考方案4】:
箭头函数 this
在 Es6 中指向周围的父级,这意味着它不像 ES5 中的匿名函数那样作用域...
这是避免将 var self 分配给 this 的非常有用的方法,这在 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…
【讨论】:
【参考方案5】:您可以按照下面的方法尝试理解它
// 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',.apply不会,.call不会,.bind不会。 当你在文本编辑器中写下代码文本时,胖箭头函数中的'this'被绑定。胖箭头函数中的“this”在这里实际上是有意义的。您在文本编辑器中编写的代码就是您的应用在 repl 中运行的内容。 除非您在文本编辑器中更改它,否则胖箭头中绑定的“this”永远不会改变。 对不起,我的泳池英语......
【讨论】:
【参考方案6】:再举个例子,如果你点击下方的年龄按钮
<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 错误:未捕获的类型错误:无法读取属性 第 18 行未定义的“getFullYear”
但是如果你改变 person2 的这一行
return new Date().getFullYear() - this.dob.getFullYear();
到
return new Date().getFullYear() - person2.dob.getFullYear();
它会起作用,因为这个范围在 person2 中发生了变化
【讨论】:
【参考方案7】:箭头函数永远不会与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'
【讨论】:
【参考方案8】:this 在箭头函数中使用时将始终引用全局对象。使用常规函数声明来引用本地对象。此外,您可以使用对象名称作为上下文(object.method,而不是 this.method),以便它引用本地对象而不是全局(窗口)。
【讨论】:
【参考方案9】:箭头函数与常规函数的区别:(取自w3schools)
使用箭头函数没有 this 的绑定。
在常规函数中,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>
【讨论】:
【参考方案10】:一个相关的问题:
来自 - Why can't I access `this` within an arrow function?
我们从这里知道:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
没有自己的绑定到 this 或 super,不应用作方法。
箭头函数根据定义箭头函数的范围建立“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
【讨论】:
以上是关于ES6 中的箭头函数中的“this”指的是啥?的主要内容,如果未能解决你的问题,请参考以下文章