title | comments | date | type | categories | tags | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
'this' & arrow function |
true |
2018-09-05 14:51:55 -0700 |
categories |
Full stack |
|
-
what is
this
?- all regular functions have
this
keyword this
determines how a function is called on whom!
- all regular functions have
-
this
in global context-
this
refers gloabl object, no matter in strict mode or not// In web browsers, the window object is also the global object: console.log(this === window); // true a = 37; console.log(window.a); // 37 this.b = "MDN"; console.log(window.b) // "MDN" console.log(b) // "MDN"
-
-
this
in function context [important]There are 7 cases that different function context results in different
this
reference;The value of
this
depend on how the function is called-
this
in simple call-
non-strict mode
if
this
is not set explicitly, it default to global objectfunction f1() { return this; } // In a browser: f1() === window; // true // In Node: f1() === global; // true
-
strict mode
if
this
is not set explicitly, the value ofthis
remainsundefined
-
function f2() { 'use strict'; // see strict mode return this; } f2() === undefined; // true
-
change the value of
this
, usingapply()
orcall()
// An object can be passed as the first argument to call or apply and this will be bound to it. var obj = {a: 'Custom'}; // This property is set on the global object var a = 'Global'; function whatsThis() { return this.a; // The value of this is dependent on how the function is called } whatsThis(); // 'Global' whatsThis.call(obj); // 'Custom' whatsThis.apply(obj); // 'Custom'
-
-
this
inbind()
method-
NOTE:
bind()
doesn't change the orignal function, instead it return a new function with updated value ofthis
function f() { return this.a; } var g = f.bind({a: 'azerty'}); console.log(g()); // azerty var h = g.bind({a: 'yoo'}); // bind only works once! console.log(h()); // azerty var o = {a: 37, f: f, g: g, h: h}; console.log(o.a, o.f(), o.g(), o.h()); // 37,37, azerty, azerty
-
-
this
in arrow function-
this
cannot be changed, it default to the value of the enclosing lexical context'sthis
-
var globalObject = this; var foo = (() => this); console.log(foo() === globalObject); // true
-
About
call()
&apply()
-
if
this
arg is passed to call, bind, or apply on invocation of an arrow function it will be ignored. -
the
thisArg
still works -
// Call as a method of an object var obj = {func: foo}; console.log(obj.func() === globalObject); // true // Attempt to set this using call console.log(foo.call(obj) === globalObject); // true // Attempt to set this using bind foo = foo.bind(obj); console.log(foo() === globalObject); // true
another example:
this
of arrow function, directly depends on its enclosing context// Create obj with a method bar that returns a function that // returns its this. The returned function is created as // an arrow function, so its this is permanently bound to the // this of its enclosing function. The value of bar can be set // in the call, which in turn sets the value of the // returned function. var obj = {bar: function() { var x = (() => this); return x; } }; // Call bar as a method of obj, setting its this to obj // Assign a reference to the returned function to fn var fn = obj.bar(); // Call fn without setting this, would normally default // to the global object or undefined in strict mode console.log(fn() === obj); // true // But caution if you reference the method of obj without calling it var fn2 = obj.bar; // Then calling the arrow function this is equals to window because it follows the this from bar. console.log(fn2()() == window); // true
-
-
-
this
in object method-
When a function is called as a method of an object, its
this
is set to the object the method is called on. -
var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); // 37
-
this
on the object's prototype chainIf the method is on an object's prototype chain,
this
refers to the object the method was called on, as if the method were on the object.
-
-
this
in constructor-
this
is bound to the new object being constructed -
#A# if
constructor
doesn't return: result ofnew
will be the object bound tothis
-
#B# if
constructor
return an object: result ofnew
will be the return value -
function C() { this.a = 37; } var o = new C(); console.log(o.a); // 37 function C2() { this.a = 37; return {a: 38}; } // if an object was returned during construction, then the new object that this was bound to simply gets discarded. o = new C2(); console.log(o.a); // 38
-
-
this
in DOM event handler-
this
is set to the target element the event fired from -
// When called as a listener, turns the related element blue function bluify(e) { // Always true console.log(this === e.currentTarget); // true when currentTarget and target are the same object console.log(this === e.target); this.style.backgroundColor = '#A5D9F3'; } // Get a list of every element in the document var elements = document.getElementsByTagName('*'); // Add bluify as a click listener so when the // element is clicked on, it turns blue for (var i = 0; i < elements.length; i++) { elements[i].addEventListener('click', bluify, false); }
-
-
this
in inline event handler-
this
is set to the DOM element where the listener is placed -
however, only the outer code has its
this
set this way -
<!-- 1. this will refer to 'button' --> <button onclick="alert(this.tagName.toLowerCase());"> Show this </button> <!-- 2. 'this' will refer to 'window' --> <button onclick="alert((function() { return this; })());"> Show inner this </button>
-
-
-
Best suited for non-method functions, ie. not related to method in object
-
No separate
this
of its own, using others'-
An arrow function does not have its own
this
-
this
value of the enclosing lexical context is used -
how to find
this
of enclosing lexical context:-
check if
this
is present in current scope; -
check
this
is present in its enclosing scope; -
//---------- version1: works ----------------- function Person(){ this.age = 0; setInterval(() => { this.age++; // |this| properly refers to the Person object }, 1000); } var p = new Person(); //---------- version2: doesn't work ---------- function Person() { // The Person() constructor defines `this` as an instance of itself. this.age = 0; setInterval(function growUp() { // In non-strict mode, the growUp() function defines `this` // as the global object (because it's where growUp() is executed.), // which is different from the `this` // defined by the Person() constructor. this.age++; }, 1000); } var p = new Person();
-
-
-
No binding of
arguments
-
Arrow functions do not have their own
arguments
object. -
var arguments = [1, 2, 3]; var arr = () => arguments[0]; arr(); // 1 function foo(n) { var f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n return f(); } foo(3); // 6
-
using rest parameters is a good alternative to using an
arguments
object -
function foo(n) { var f = (...args) => args[0] + n; return f(10); } foo(1); // 11
-
-
When not use arrow function? ==> when need
this
explicitly-
don't use as methods of object:
-
because we need
this
, but arrow function doesn't have its ownthis
-
'use strict'; var obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log(this.i, this); } } obj.b(); // prints undefined, Window {...} (or the global object) obj.c(); // prints 10, Object {...}
-
-
don't use as function constructor: because we will use
new
to construct , which needthis
-
don't add
prototype
to it: because it doesn't havethis
-
don't use in
yeild
orgenerators
:
-