Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a4add25

Browse files
committed
JS this keyword STATUS:DONE
1 parent 11e0262 commit a4add25

File tree

3 files changed

+299
-11
lines changed

3 files changed

+299
-11
lines changed

β€Ž01-Javascript-Engine.mdβ€Ž

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,16 @@ To summarize, - At first, greet() is added to the call stack. - greet() then cal
7878

7979
At this point, the call stack status is currently -
8080

81-
+++++++++++++++++++<br>
82-
Call Stack<br>
83-
+++++++++++++++++++<br>
84-
sayHello()<br>
85-
greet()<br>
86-
+++++++++++++++++++<br>
81+
| Call Stack |
82+
| ---------- |
83+
| sayHello() |
84+
| greet() |
8785

8886
sayhello() is now at the top of the stack and is executed. It prints out **Hello** to the console and is removed from the stack.
8987

90-
+++++++++++++++++++<br>
91-
Call Stack<br>
92-
+++++++++++++++++++<br>
93-
greet()<br>
94-
+++++++++++++++++++<br>
88+
| Call Stack |
89+
| ---------- |
90+
| greet() |
9591

9692
Now, greet() is at the top of the stack and prints out **I am robot** to the console and thus removed from the stack.
9793

β€Ž10-JavaScript-Functions.mdβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,3 +410,5 @@ function power(a, n) {
410410
- `unshift()`: adds one or more elements to the front of array and returns the new length of array
411411
- `slice()`: extracts a section of array and returns a new array
412412
- `splice()`: add, remove or replace elements in an array based on their index
413+
414+
[<-- Previous [Operators in JavaScript]](./09-JavaScript-Operators.md) <div style="text-align: right;"> [Next [JavaScript `this` Keyword] -->](./11-JavaScript-%60this%60-Keyword.md)</div>
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
# `this` Keyword
2+
3+
In simple terms, `this` keyword in JavaScript refers to an object upon which a function is invoked. This means that `this` can only be used in a function, or globally.
4+
5+
`this` is used to point to an instance of an object from its own constructor or its method and also to keep track of the execution context (lexical scope) - which is often based on where the function is called from.
6+
7+
```js
8+
function myself() {
9+
this.name = "Prabesh";
10+
console.log(this); // OUTPUT: myself {"name": "Prabesh"}
11+
}
12+
13+
let intro = new myself();
14+
```
15+
16+
In the example above, `myself` is used as constructor for the object of type `myself`. Here, `this` reference points to itself i.e. myself {name: "Prabesh"}.
17+
18+
When we use the `new` keyword to create an instance of the `myself()` function, it creates new object and sets `this` to refer to that object. In this case, the `name` property is set to the new object created by the `new` operator.
19+
20+
So, when we create a new instance of `myself()` using `let intro = new myself()`, the `name` property is set on the newly created object, and `this` refers to that object. Therefore, `intro` will refer to an object with a `name` property of "Prabesh".
21+
22+
## `this` in function
23+
24+
When used in either of function or globally, `this` refers to the window object.
25+
26+
```js
27+
function foo() {
28+
console.log(this);
29+
}
30+
31+
foo(); // OUTPUT : Window
32+
```
33+
34+
Here, when we call the `foo()` function without `new` keyword, `this` refers to the global object (which could be `window` in browser or `global` in Node.js).
35+
36+
However, when we want to use the function as constructor of an object (create an object of type `foo`), `this` keyword changes its context to the instance of `bar` object itself and no longer global object.
37+
38+
```js
39+
function foo() {
40+
console.log(this);
41+
}
42+
43+
let bar = new foo(); //Output: foo{}
44+
typeof bar; //Ouput: 'object'
45+
```
46+
47+
## `this` in methods
48+
49+
When a function is a method of an object, then `this` refers to object that the method is a member of. This allows us to access and manipulate the properties of the object within the method.
50+
51+
_Example:_
52+
53+
```js
54+
const user = {
55+
name: "Prabesh",
56+
age: 23,
57+
greet: function () {
58+
console.log(`Hello, my name is ${this.name}`);
59+
},
60+
};
61+
62+
user.greet(); // Output: "Hello, my name is Prabesh"
63+
```
64+
65+
In the above example, `user` is an object that has a `greet()` method. When we call `user.greet()`, `this` refers to the `user` object. Hence, within the `greet()` method, we can access the `name` property of `user` object using `this.name`.
66+
67+
## `this` in event handlers
68+
69+
The value of `this` inside handler function may not be what we expect it to be. The value of `this` inside an event handler function is determined by how the function is called. In most cases, `this` will refer to DOM element that triggered the event.
70+
71+
For example, if you have a button with an `onClick` attribute that calls a function, the value of `this` inside that function will be the button element. We can use `this` keyword to access properties and methods of the object that the event is asscoiated with. For example, we can use `this.textContent` property to get the text content of the button object.
72+
73+
```php
74+
<button id="myButton">Click me</button>
75+
76+
<script>
77+
function myFunction() {
78+
console.log(this); // logs the button element
79+
// Output: <button id="myButton">Click me</button>
80+
}
81+
82+
// Attach the event handler to the button's click event.
83+
document.getElementById("myButton").addEventListener("click", myFunction);
84+
</script>
85+
```
86+
87+
When the button is clicked, the `myClickHandler()` function will be called. The `this` keyword will refer to the button object, so you can use the `this` keyword to access and modify the button's properties and methods.
88+
89+
Now, let's consider annther example:
90+
91+
```js
92+
function cookFood(dish) {
93+
this.dish = dish;
94+
this.time = time;
95+
96+
function setTime(sec) {
97+
setTimeout(function () {
98+
console.log(this.dish + " cooked for " + sec + " seconds");
99+
}, sec * 1000);
100+
}
101+
}
102+
103+
let curry = new cookFood("Curry"); // this.dish = "Curry"
104+
curry.setTime(3); // Output: undefined cooked for 2 seconds
105+
```
106+
107+
So, what happened here? We have set `this.dish="Curry"` when constructing the `cookFood` object but we get "undefined cooked for 2 seconds" when we expected the output to be "Curry cooked for 2 seconds".
108+
109+
Here, when we call the `setTimeout` function, it creates a nre execution context for the anonymous function that we pass as an argument, which has its own `this` context. Hence, when the anonymous function executes, `this.dish` will be `undefined` because `this` refers to the global object, not the `cookFood` object we created.
110+
111+
This is where arrow functions comes into rescue.
112+
113+
## `this` in arrow functions
114+
115+
Arrow functions help us write more concise and efficient code. Arrow functions does not create it's own execution context but inherits `this` from outside function where the function is defined.
116+
117+
Therefore, the problem in the above code can be fixed just br replacing the regular function for the anonymous function with arrow function.
118+
119+
```js
120+
function cookFood(dish) {
121+
this.dish = dish;
122+
this.time = time;
123+
124+
function setTime(sec) {
125+
setTimeout(() => {
126+
console.log(this.dish + " cooked for " + sec + " seconds");
127+
}, sec * 1000);
128+
}
129+
}
130+
131+
let curry = new cookFood("Curry"); // this.dish = "Curry"
132+
curry.setTime(3); // Output: Curry cooked for 2 seconds
133+
```
134+
135+
Since, arrow functions do not create their own `this` context. the `this` will refer to the `cookFood` object we created.
136+
137+
# Function Borrowing
138+
139+
Function borrowing is a concept that allows us to reuse the methods of one object on another object. Simply put, we can borrow the methods of one object and use them on other object.
140+
141+
## Implicit Binding
142+
143+
Implicit binding is the default way that `this` is determined in a function call. Whenever we invoke a method of an object using the dot notation, the `this` keyword will point to the object with which it was invoked. In simple terms, when a function is called as a method of an object, `this` is set to the object itself.
144+
145+
```js
146+
const user = {
147+
name: "John",
148+
greetUser: function () {
149+
console.log("Welcome to JavaScript " + this.name);
150+
},
151+
};
152+
153+
user.greetUser(); // Output: "Welcome to JavaScript John"
154+
```
155+
156+
In this example, `greetUser()` is called as a method of `user`, so `this` is set to `user`.
157+
158+
## Explicit Binding
159+
160+
Explicit binding in JavaScript refers to the technique of manually setting the `this` keyword inisde a function using the `call()`, `apply()` or `bind()` methods. We use explicit binding when we want to access the methods of an object with the values provided by another object.
161+
162+
### 🀝 bind()
163+
164+
The `bind()` method creates and returns a new function, whose `this` keyword is set to object which was passed to it. It _binds_ a method to an object and returns to be invoked later.
165+
166+
```js
167+
function greet() {
168+
console.log("Welcome " + this.name);
169+
}
170+
171+
const user1 = {
172+
name: "Prabesh",
173+
};
174+
175+
const user2 = {
176+
name: "Laxmi",
177+
};
178+
179+
const greetUser1 = greet.bind(user1);
180+
const greetUser2 = greet.bind(user2);
181+
182+
greetUser1(); // Output: "Welcome Prabesh"
183+
greetUser2(); // Output: "Welcome Laxmi"
184+
```
185+
186+
In the above example, we have function `greet()` and objects `user1` and `user2` with `name` properties. We are using the `bind()` method to create two new functions `greetUser1()` and `greetUser2()` which
187+
have their `this` value bound to `user1` and `user2` respectively.
188+
189+
Let's have a look at another example:
190+
191+
```js
192+
const user = {
193+
firstName: "Super",
194+
lastName: "Mario",
195+
greet: function () {
196+
console.log("Hello, I am " + this.firstName + " " + this.lastName + ".");
197+
},
198+
};
199+
200+
user.greet(); // Output: "Hello, I am Super Mario."
201+
202+
const user2 = {
203+
firstName: "Bob",
204+
lastName: "Builder",
205+
};
206+
207+
const intro = user.greet.bind(user2);
208+
intro(); // Output: Hello, I am Bob Builder.
209+
```
210+
211+
Here, we defined an object call `user` that has three properties: `firstName`, `lastName` and `greet`. The `greet` property is a function that logs a message including `firstName` and `lastName`. When we call `user.greet()`, we are invoking the `greet` function with `this` referring to `user` object. Hence, we get a output of "Hello, I am Super Mario". This concept is referred as `impilicit binding`.
212+
213+
Next, we define another object called `user2` that has two properties: `firstName` and `lastName`. We then create a function called `intro` by using the `bind()` method to bind the `this` keyword of the `greet` function to the `user2` object. This means when we call `intro()` function, `this` inside the `greet` function will refer to the `user2` object and the output will be "Hello, I am Bob Builder."
214+
215+
To summarize, by using `bind()`, we are essentially creating a new function that has its `this` value set to `user2` object. This allows us to resue the `greet` function with a different object. This concept is referred as `explicit binding`.
216+
217+
### πŸ€™ call()
218+
219+
The `call()` method works similar to `bind()` but has one major difference. As we know, `bind()` method returns a function that can be invoked later but the `call()` method invokes a function and returns the result.
220+
221+
```js
222+
function greet() {
223+
console.log("Hello, my name is " + this.name);
224+
}
225+
226+
const person = {
227+
name: "Ninja",
228+
};
229+
230+
greet.call(person); // Output: "Hello, my name is Ninja"
231+
```
232+
233+
Here, we hava a `greet` function and an object `person` with a `name` property. We are using the `call()` method to call `greet()` function with `person` as the context to `this`. As a result, we get an output of "Hello, my name is Ninja".
234+
235+
let us consider another example:
236+
237+
```js
238+
const user = {
239+
firstName: "Sonic",
240+
lastName: "Hedgehog",
241+
greet: function (place) {
242+
console.log(`I am ${this.firstName} ${this.lastName} from ${place}`);
243+
},
244+
};
245+
246+
user.greet("Colorado"); // Output: I am Sonic Hedgehog from Colorado
247+
248+
const user2 = {
249+
firstName: "Ninja",
250+
lastName: "Turtle",
251+
};
252+
253+
user.greet.call(user2, "Texas"); // Output: I am Ninja Turtle from Texas
254+
```
255+
256+
In this example, we have two objects: `user` and `user2`. We are borrowing the `greet()` function from `user` object using `call()` method abnd binding it with `user2` object.
257+
258+
By using the `call()` method, we are invoking the `greet` function in the context of `user2` object. The first argument to `call()` is the object that `this` should refer to inside the fucntion, and any subsequent arguments are passed as arguments to the function itself.
259+
260+
### πŸ‘ apply()
261+
262+
The `apply()` method is similar to `call()` method, but takes an array of arguments instead of inidividual arguments. In the `call()` method, we can pass multiple parameters, but in `apply()` method, we have to pass in single array that would contain all the parameters.
263+
264+
```js
265+
const user = {
266+
firstName: "Cristiano",
267+
lastName: "Ronaldo",
268+
greet: function (club, country) {
269+
console.log(
270+
`I am ${this.firstName} ${this.lastName} from ${country} playing for ${club}.`
271+
);
272+
},
273+
};
274+
275+
user.greet("Al-Nassr", "Portugal"); // Output: I am Cristiano Ronaldo from Portugal playing for Al-Nassr.
276+
277+
const user2 = {
278+
firstName: "Lionel",
279+
lastName: "Messi",
280+
};
281+
282+
user.greet.apply(user2, ["PSG", "Argentina"]); // Output: I am Lionel Messi from Argentina playing for PSG.
283+
```
284+
285+
By using `apply()`, we're essentially invoking the `greet` function in the context of the `user2` object. The first argument to `apply()` is the object that `this` should refer to inside the function, and the second argument is an array of arguments to pass to the function itself. In this case, we're passing an array of two elements, "PSG" and "Argentina", which are used as the `club` and `country` parameters in the `greet` function, respectively.
286+
287+
**_Summary:_**
288+
289+
- By default, the methods of an object are implicitly bounded to the object itself, and we can access them using the dot (.) operator.
290+
- To access the methods of other objects, we need to explicitly bind them to the object using the `bind()`, `call()`, or `apply()` methods, with each one of them having its own use cases.

0 commit comments

Comments
(0)

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /