1
+ /********************************************************************************************
2
+ * Execution Context in Detail - The "this" Keyword
3
+ * ------------------------------------------------
4
+ *
5
+ * We can associate an execution context with an object, i.e., an execution context can be
6
+ * thought of as an object. This object (i.e., the execution context) has 3 properties,
7
+ * namely:
8
+ * 1. Variable Object (VO): contains function arguments, function's inner variable
9
+ * declarations, as well as function declarations.
10
+ * 2. Scope Chain: contains current variable's objects as well as variable objects of all its
11
+ * parents.
12
+ * 3. "this" variable: which is an object that refers to the current execution context's
13
+ * object.
14
+ *
15
+ * How's this execution context actually created?
16
+ * -> By what we already know, we can say that when a function is called, a new execution
17
+ * context is created on top of the stack.
18
+ * This happens in two phases:
19
+ *
20
+ * 1. Creation Phase: In this phase, again there are 3 phases:
21
+ * 1. Creation of the Variable Object (VO).
22
+ * 2. Creation of the Scope Chain. [Huge topic, we'll know about
23
+ * this topic later]
24
+ * 3. Determine the value of the "this" variable.
25
+ *
26
+ * 2. Execution Phase: The code of the function that generated the current execution
27
+ * context is run line by line & all the variables are defined.
28
+ * If it is a global execution context, then the global context's
29
+ * code is executed line by line.
30
+ *
31
+ * 1.3. Determine the value of the "this" variable:
32
+ * -> Before knowing how the "this" variable is created, we should know the
33
+ * difference between functions and methods.
34
+ * function: is defined/created in the global execution context or in some
35
+ * other function's execution context (which is not defined in
36
+ * some other object).
37
+ * method: is defined/created in the execution context of an object, i.e.,
38
+ * a property inside a JS object which is a function, is a method.
39
+ *
40
+ * The "this" variable is a variable that each and every execution context gets
41
+ * by default and as we already know, the "this" variable is stored in the
42
+ * execution context's object (as shown above).
43
+ * The "this" variable points to different things depending on what's happening
44
+ * in the program currently, i.e., if there's a:
45
+ * 1. Regular function call: the "this" variable simply points at the global
46
+ * object (the window object, in case of the browser).
47
+ * 2. Method call: the "this" variable points to the object that is calling the
48
+ * method.
49
+ * Note: The "this" variable is not assigned a value, until the function where it
50
+ * is defined, is actually called/invoked.
51
+ *
52
+ * We'll see the usage of the "this" variable in practice, down below:
53
+ */
54
+
55
+ /////////////////////////////////////////////////////////////////////////////////////////////
56
+
57
+ // Normally, the "this" variable always points to the window object
58
+ console . log ( this ) ;
59
+ console . log ( "-----------------------------------------------------------------------------" ) ;
60
+
61
+ /////////////////////////////////////////////////////////////////////////////////////////////
62
+
63
+ /* "this" variable's value in a regular function call */
64
+ console . log ( "Call of calculateAge()" ) ;
65
+ calculateAge ( 1995 ) ; // possible because of hoisting
66
+
67
+ function calculateAge ( yob ) { // yob: Year of Birth
68
+ var currYear = 2019 ;
69
+ console . log ( currYear - yob ) ;
70
+ console . log ( this ) ;
71
+ // Since calculateAge() is a regular function, the "this" variable invoked in this
72
+ // context will point to the global execution context (which is the window object).
73
+ }
74
+ console . log ( "-----------------------------------------------------------------------------" ) ;
75
+
76
+ /////////////////////////////////////////////////////////////////////////////////////////////
77
+
78
+ /* "this" variable's value in a method call (i.e., a function defined inside a JS Object) */
79
+ var john = {
80
+ name : "John" ,
81
+ yob : 1990 , // yob: Year of Birth
82
+ calculateAge : function ( ) {
83
+ var currYear = 2019 ;
84
+ console . log ( currYear - this . yob ) ;
85
+ console . log ( this ) ;
86
+ // The "this" variable invoked here would point to the "john" object, because here,
87
+ // the we have a method definition.
88
+
89
+ // The following might be a weird behaviour, but it is perfectly valid in JS
90
+ function innerFunction ( ) {
91
+ console . log ( this ) ;
92
+ // The "this" variable invoked at this space, actually points to the global
93
+ // execution context (which is the window object). But why?
94
+ // The reason is simple, but yet, a little confusing to digest.
95
+ // The "this" variable points to an object, only when it is invoked in a method,
96
+ // i.e., john.calculateAge() for this example. But, the innerFunction(), is
97
+ // actually another function inside of the "john" object's property, which is,
98
+ // a function defined inside the calculateAge property. Therefore, this function,
99
+ // i.e., innerFunction() turns out to be a Regular function defined inside a
100
+ // Method, and as we already know, a regular function call, has the "this"
101
+ // variable always pointing to the global execution context (which is the
102
+ // window object), and therefore, the "this" variable inside the innerFunction
103
+ // will point to the window object.
104
+ }
105
+
106
+ console . log ( "Call of innerFunction()" ) ;
107
+ innerFunction ( ) ;
108
+ }
109
+ } ;
110
+
111
+ console . log ( "Call of john.calculateAge()" ) ;
112
+ john . calculateAge ( ) ;
113
+ console . log ( "-----------------------------------------------------------------------------" ) ;
114
+
115
+ /////////////////////////////////////////////////////////////////////////////////////////////
116
+
117
+ /* Method Borrowing */
118
+ // an object of one type can borrow the methods of another object other type,
119
+ // but the borrowing makes "this" variable point to their respective caller objects.
120
+ // Example illustrated below:
121
+ var mike = {
122
+ name : "Mike" ,
123
+ yob : 1990 , // yob: Year of Birth
124
+ calculateAge : function ( ) {
125
+ console . log ( this ) ;
126
+ var currYear = 2019 ;
127
+ console . log ( currYear - this . yob ) ;
128
+ }
129
+ } ;
130
+
131
+ console . log ( "Call for mike.calculateAge()" ) ;
132
+ mike . calculateAge ( ) ; // "this" variable will point to "mike" object.
133
+
134
+ var maya = {
135
+ name : "Maya" ,
136
+ yob : 1998 // yob: Year of Birth
137
+ } ;
138
+
139
+ // Usage of method borrowing: (used very often in JS)
140
+ maya . calculateAge = mike . calculateAge ;
141
+
142
+ // now we can call calaculateAge from maya, but the "this" variable in "maya" object
143
+ // will point to the "maya" object and not the "mike" object.
144
+ console . log ( "Call for maya.calculateAge()" ) ;
145
+ maya . calculateAge ( ) ;
0 commit comments