What does “this” refer to in arrow functions in ES6?

霸气de小男生 提交于 2019-11-25 21:45:25

问题


I\'ve read in several places that the key difference is that \"this is lexically bound in arrow functions.\" That\'s all well and good, but I don\'t actually know what that means.

I know it means it\'s unique within the confines of the braces defining the function\'s body, but I couldn\'t actually tell you the output of the following code, because I have no idea what this is referring to, unless it\'s referring to the fat arrow function itself....which doesn\'t seem useful.

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

回答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();

So, to directly answer your question, this inside your arrow function would have the same value as it did right before the arrow function was assigned.




回答2:


In order to provide the big picture I'm going to explain both, dynamic and lexical binding.

Dynamic Name Binding

this refers to the object the method is called on. This is a regularly to be read sentence on SO. But it is still only a phrase, pretty abstract. Is there a corresponding code pattern to this sentence?

Yes there is:

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

// the important patterns: applying methods

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

m is a method because it relies on this. o.m() or o["m"]() means m is applied to o. These patterns are the Javascript translation to our famous phrase.

There is another important code pattern that you should pay attention to:

"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

It is very similar to the previous pattern, only the parenthesis are missing. But the consequences are considerable: When you pass m to the function f, you pull outm of its object/context o. It is uprooted now and this refers to nothing (strict mode assumed).

Lexical (or Static) Name Binding

Arrow functions don't have their own this/super/arguments binding. They inherit them from their parent lexical scope:

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]

Apart from the global scope (Window in browsers) only functions are able to form a scope in Javascript (and {} blocks in ES2015). When the o.foo arrow function is called there is no surrounding function from which baz could inherit its this. Consequently it captures the this binding of the global scope which is bound to the Window object.

When baz is invoked by o.bar, the arrow function is surrounded by o.bar (o.bar forms its parent lexical scope) and can inherit o.bar's this binding. o.bar was called on o and thus its this is bound to o.




回答3:


Hope this code show could give you clearer idea. Basically, 'this' in arrow function is the current context version of 'this'. See the code:

// '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 



回答4:


Arrow function this is pointing to the surrounding parent in Es6, means it doesn't scope like anonymous functions in ES5...

It's very useful way to avoid assigning var self to this which is widely used in ES5...

Look at the example below, assigning a function inside an object:

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:


You can try to understand it by following the way below

// 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]
}

so 'this' in fat arrow function is not bound, means you can not make anything bind to 'this' here, .apply won't, .call won't, .bind won't. 'this' in fat arrow function is bound when you write down the code text in your text editor. 'this' in fat arrow function is literally meaningful here. What your code write here in text editor is what your app run there in repl. What 'this' bound in fat arror will never change unless you change it in text editor. Sorry for my pool English...




回答6:


In another example, if you click the age button below

<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">

it will throw an exception like this

×JavaScript error: Uncaught TypeError: Cannot read property 'getFullYear' of undefined on line 18

But if you change person2's this line

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

to

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

it will work because this scope has changed in person2




回答7:


Arrow function never binds with this keyword

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'


来源:https://stackoverflow.com/questions/28371982/what-does-this-refer-to-in-arrow-functions-in-es6

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!