# Czym jest this ?

Słowo kluczowe this jest wskaźnikiem wskazującym na obiekt, który wywołał funkcję.

TIP

Niestety this w JavaScripcie moze wskazywać na różne wartości w zależnosci od miejsca (kontekstu) w ktorym zostal wywolany (execution context) - aczkolwiek ostatecznie this jest określany przez sposob w jaki jest wykonywana dana funkcja - tzn, że jesteśmy w stanie sami określić i przekazać konteskt - za pomocą funkcji takich jak bind, apply czy call.

Aby dobrze zrozumieć oraz wiedzieć na co w danym momencie będzie wskazywał this zapoznaj się z poniższymi zadaniami. Spróbój samemu odgadnąć czym będzie this a następnie odkomentuj wywołanie kodu.

Wszystkie zadania są dostępne też tutaj: https://codesandbox.io/s/js-this-forked-mxeqc?file=/index.html (opens new window)

# 1. Person

// 1. Co będzie wynikiem wywołania person.greet() ?
// 1.2. Co jest kontekstem wywołania funkcji greet() ?
var person = {
  name: "Jay",
  greet: function () {
    console.log("hello, " + this.name);
  }
};

function greet() {
  console.log("hello, " + this.name);
}
// person.greet();


// 2.Co będzie wynikiem wywołania metody greet() ?
// const greet = person.greet;
// greet();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

TIP

Wartość this nie jest określana przez miejsce, w którym się znajduje, lecz przez sposób w jaki jest wykonywana.

# 2. Where this is

/* eslint-disable */
// 1. Co będzie wynikiem wywołania poniszego kodu ?
var name = "Jay Global";
var person = {
  name: "Jay Person",
  details: {
    name: "Jay Details",
    print: function () {
      return this.name;
    }
  },
  print: function () {
    return this.name;
  }
};
// console.log(person.details.print()); // ??
// console.log(person.print()); // ??

var name1 = person.print;
var name2 = person.details;

// console.log(name1()); // ??
// console.log(name2.print()); // ??

// 2. Co będzie wynikiem wywołania poniŻszego kodu ?
// var car = {
//   brand: "Nissan",
//   getBrand: function () {
//     console.log(this.brand);
//   }
// };

// var getCarBrand = car.getBrand;

// getCarBrand();

// 3. Co bedzie wynikiem wywolania poniszego kodu ?
// const call = {
//   caller: "mom",
//   says: function () {
//     console.log(`Hey, ${this.caller} just called.`);
//   }
// };

// call.says();

///////////////

// const call = {
//   caller: "mom",
//   says: () => {
//     console.log(`Hey, ${this.caller} just called.`);
//   }
// };

// call.says();

///////////////

// const call = {
//   caller: "mom",
//   says: function () {
//     console.log(`Hey, ${this.caller} just called.`);
//   }
// };

// let newCall = call.says;

// newCall();

///////////////

// function anotherCaller() {
//   console.log(`${this.caller} called, too!`);
// }

// const call = {
//   caller: "mom",
//   anotherCaller,
//   says: function () {
//     console.log(`Hey, ${this.caller} just called.`);
//   }
// };

// const newCall = call.anotherCaller;

// newCall();

//
// https://dev.to/liaowow/take-this-quiz-understand-how-this-works-in-javascript-44dj
// https://www.sitepoint.com/mastering-javascripts-this-keyword/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# 3. Arrow functions

// Co bedzie wynikiem wykonania poniszego kodu ?
// 1. Na co wskazuje ponizszy this ?
// const myFunction = () => {
//   console.log(this);
// };

// myFunction();

// 2. Na co wskazuje ponizszy this ?
// const myObject = {
//   myMethod: () => {
//     console.log(this);
//   }
// };

// myObject.myMethod();

// 3. Na co wskazuje ponizszy this ?
// function Car() {
//   console.log(this);
// }

// let car = new Car();

// 4.
// function Car() {
//   this.speed = 0;

//   this.speedUp = function (speed) {
//     setTimeout(() => console.log(this.speed + speed), 1000);
//   };
// }

// let car = new Car();
// car.speedUp(50); // 50;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

TIP

this wewnatrz funkcji strzalkowej wskazuje zawsze na "lexical scope"

# 4. Use strict

// 1. Jak use strict wplywa na this ?
// (function () {
//   "use strict";
//   console.log(this);
// })();
// (function () {
//   // Without strict mode
//   console.log(this);
// })();

// 2. Co bedzie wynikiem wywołania kodu z wiersza 21 ?
// (function () {
//   "use strict";
//   var item = {
//     document: "My document",
//     getDoc: function () {
//       return this.document;
//     }
//   };
//   var getDoc = item.getDoc;
//   console.log(getDoc());
// })();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

TIP

use strict chroni nas od niepozadanych operacji na obiekcie window.

# 5. onClick

function clickMe() {
  console.log(this);
}

// 1. czym bedzie this ?
// document
//   .getElementById("example-button")
//   .addEventListener("click", function () {
//     console.log(this);
//   });

// 2. czym bedzie this ?
// document.getElementById("example-button").addEventListener("click", () => {
//   console.log(this);
// });

// 2.1 Jak zapewnic sobie element, kiedy nie mamy kontekstu ?
// document.getElementById("example-button").addEventListener("click", (event) => {
//   console.log(event.currentTarget);
// });

var car = {
  brand: "Nissan",
  getBrand: function () {
    console.log(this.brand);
  }
};

// document
//   .getElementById("example-button")
//   .addEventListener("click", car.getBrand);

// Wrocmy tutaj po bind/apply/call
// 3.Przekaz inny obiekt w momencie wywolania eventu click
// document.getElementById("example-button").addEventListener("click", clickMe);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 6. use Bind

TIP

metoda bind pozwala nam na utworzenie metody oraz przypisaniu do niej nowego kontekstu

// 1. Co bedzie wynikiem wykonania się wiersza 10?
// var bobObj = {
//   name: "Bob"
// };

// function print() {
//   return this.name;
// }

// console.log(print());

// 1.2 Napraw powyższą metode print

// 1.3 Co bedzie wynikiem wywolania ?
// var car = {
//   brand: "Nissan",
//   getBrand: function () {
//     var closure = function () {
//       console.log(this.brand);
//     };
//     return closure();
//   }
// };

// car.getBrand();

// 2. Utwórz metodę, która wywoła obj2.printSecondData na zestawie danych z obj1
// poprawny wynik powinien być równy === 2
// var obj1 = {
//   data: [1, 2, 3],
//   printFirstData: function () {
//     if (this.data.length) return this.data[0];
//   }
// };

// var obj2 = {
//   data: [4, 5, 6],
//   printSecondData: function () {
//     if (this.data.length > 1) return this.data[1];
//   }
// };

// 3.Zmodyfikuj tak funkcję double aby wiersz 34 poprawnie wskazywał na zawartość obiektu "object"
// var object = {
//   data: [1, 2, 3],
//   double: function () {
//     this.data.forEach(function () {
//       // Get this to point to object.
//       console.log(this);
//     });
//   }
// };

// object.double();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 7. use Apply

TIP

metoda apply równiez pozwala nam na przypisanie kontesktu do metody z tą różnicą, że apply automatycznie wykona tę metodę

// 1. Wywolaj metodę bark w taki sposób aby przekazać do niej poprawne name
// function Dog(name) {
//   this.name = name;
// }

// Dog.prototype.bark = function () {
//   console.log(this.name + " says woof");
// };

// const fido = new Dog("fido");

// 2. Meta Math.min zwraca najmniejszą z podanych koljeno liczb jako argumenty - nie mozna przekazać tablicy - mozemy to naprawic za pomoca apply

1
2
3
4
5
6
7
8
9
10
11
12
13

# 8. use Call

// 1. Jaki będzie wynik wywołania fuynkcji sayName ?
// let dog = {
//   name: "doggo",
//   sayName() {
//     console.log(this.name);
//   }
// };
// let sayName = dog.sayName;
// sayName();

// 2. Co będzie wynikiem wywołania następującej funkcji ?
// function convertArgs() {
//   return Array.prototype.slice.call(arguments);
// }

// console.log(convertArgs(1, 2, 3, 4, 5, 6));

// 3. document.querySelector() przyjmuje selektor css jako parametr i zwraca listę elementów typu NodeList - co nie czyni jej tablicą - jest to Array-like objects - co znaczy, ze wyglada jak tablica, ale nią nie jest - nie posiada funkcji typowych dla tablic np. includes.
// Napiszmy metodę, która przyjmie jako parametr selektor css i zwróci elementy w postaci tablicy
// console.log(document.querySelectorAll("li"));

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 9. Person Class

To jest trochę tricky - rozkmiń dlaczego 😉

// Co będzie wynikiem wywolania wiersza 17 oraz 18 ?
function Person(name, age) {
  this.name = name || "John";
  this.age = age || 24;
  this.displayName = function () {
    console.log(this.name);
  };
}

Person.prototype.name = "John";

Person.displayName = function () {
  console.log(this.name);
};

var person1 = new Person("Piotr");
person1.displayName();
Person.displayName();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18