Skip to content

Object methods, "this" #99

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions 1-js/04-object-basics/04-object-methods/2-check-syntax/solution.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
**Error**!
**Błąd**!

Try it:
Sprawdź ten kod:

```js run
let user = {
name: "John",
go: function() { alert(this.name) }
}

(user.go)() // error!
(user.go)() // błąd!
```
W większości przeglądarek wiadomość o błędzie nie zawiera zbyt wielu szczegółów mówiących co poszło nie tak.

The error message in most browsers does not give us much of a clue about what went wrong.
**Błąd wystąpił ponieważ nie ma średnika po `user = {...}`.**

**The error appears because a semicolon is missing after `user = {...}`.**

JavaScript does not auto-insert a semicolon before a bracket `(user.go)()`, so it reads the code like:
JavaScript nie wstawia automatycznie średnika przed nawiasem `(user.go)()`, więc czyta kod w ten sposób:'

```js no-beautify
let user = { go:... }(user.go)()
```

Then we can also see that such a joint expression is syntactically a call of the object `{ go: ... }` as a function with the argument `(user.go)`. And that also happens on the same line with `let user`, so the `user` object has not yet even been defined, hence the error.
Teraz widzimy, że taka składnia jest w zasadzie wywołaniem obiektu `{ go: ... }` jako funkcji z argumentem `(user.go)`. W dodatku wywołanie to znajduje się w tej samej linijce co `let user`, więc obiekt `user` nie został jeszcze nawet zdefiniowany, dlatego pojawia się błąd.

If we insert the semicolon, all is fine:
Jeśli wstawimy średnik, kod będzie działać:

```js run
let user = {
Expand All @@ -34,4 +33,4 @@ let user = {
(user.go)() // John
```

Please note that brackets around `(user.go)` do nothing here. Usually they setup the order of operations, but here the dot `.` works first anyway, so there's no effect. Only the semicolon thing matters.
Miej na uwadze, że nawiasy wokół `(user.go)` nie mają tu żadnego znaczenia. Zazwyczaj służą do zachowania kolejności wykonywania działań, jednak w tym przypadku kropka `.` i tak ma pierwszeństwo. Jedynie średnik jest tu niezbędny.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 2

---

# Syntax check
# Sprawdzenie składni

What is the result of this code?
Jaki będzie rezultat wykonania tego kodu ?


```js no-beautify
Expand All @@ -16,4 +16,4 @@ let user = {
(user.go)()
```

P.S. There's a pitfall :)
P.S. Jest tu pułapka :)
21 changes: 10 additions & 11 deletions 1-js/04-object-basics/04-object-methods/3-why-this/solution.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@

Here's the explanations.
Oto wyjaśnienie.

1. That's a regular object method call.
1. Jest to zwykłe wywołanie metody obiektu.

2. The same, brackets do not change the order of operations here, the dot is first anyway.
2. Tak jak powyżej, nawiasy nie zmieniają tutaj kolejności wykonywania działań, kropka i tak ma pierwszeństwo.

3. Here we have a more complex call `(expression).method()`. The call works as if it were split into two lines:
3. Tutaj mamy bardziej złożone wywołanie `(expression).method()`. Wywołanie działa tutaj tak jakby było rozbite na dwie linijki kodu:

```js no-beautify
f = obj.go; // calculate the expression
f(); // call what we have
f = obj.go; // przypisanie jako wartość zmiennej
f(); // wywołanie stworzonej zmiennej
```

Here `f()` is executed as a function, without `this`.
`f()` jest tutaj wywoływane jako funkcja, bez `this`.

4. The similar thing as `(3)`, to the left of the dot `.` we have an expression.
4. Podobna sytuacja jak w `(3)`, po lewej stronie od kropki `.` mamy wyrażenie.

To explain the behavior of `(3)` and `(4)` we need to recall that property accessors (dot or square brackets) return a value of the Reference Type.

Any operation on it except a method call (like assignment `=` or `||`) turns it into an ordinary value, which does not carry the information allowing to set `this`.
Żeby wyjaśnić zachowanie `(3)` i `(4)` musimy przypomnieć sobie, że akcesory właściwości (kropki lub nawiasy kwadratowe) zwracają wartość Typu Referencji.

Każda inna operacja niż wywołanie metody (jak przypisanie `=` lub `||`) zmienia Typ Referencji na zwykłą wartość, która nie zawiera informacji pozwalającej ustalić wartości `this`.
6 changes: 3 additions & 3 deletions 1-js/04-object-basics/04-object-methods/3-why-this/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 3

---

# Explain the value of "this"
# Określ wartość "this"

In the code below we intend to call `obj.go()` method 4 times in a row.
W poniższym kodzie chcemy wywołać metodę `obj.go()` cztery razy pod rząd.

But calls `(1)` and `(2)` works differently from `(3)` and `(4)`. Why?
Jednak wywołania `(1)` i `(2)` działają inaczej niż `(3)` i `(4)`. Dlaczego?

```js run no-beautify
let obj, method;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
**Answer: an error.**
**Odpowiedź: błąd.**

Try it:
Uruchom ten kod:
```js run
function makeUser() {
return {
Expand All @@ -14,26 +14,26 @@ let user = makeUser();
alert( user.ref.name ); // Error: Cannot read property 'name' of undefined
```

That's because rules that set `this` do not look at object definition. Only the moment of call matters.
Jest to spowodowane tym, że reguły ustalające wartość `this` nie uwzględniają faktu istnienia obiektu. Znaczenie ma tylko moment wywołania.

Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method with "dot" syntax.
Wartość `this` wewnątrz `makeUser()` jest `undefined`, ponieważ jest wywołana jako funkcja, a nie jako metoda wywołana za pomocą "kropki".

The value of `this` is one for the whole function, code blocks and object literals do not affect it.
Wartość `this` jest tu ustalona wyłącznie dla tej funkcji. Bloki kodu i obiekty nie są w tym przypadku brane pod uwagę.

So `ref: this` actually takes current `this` of the function.
Zatem `ref: this` jest równoznaczne z `this` funkcji.

We can rewrite the function and return the same `this` with `undefined` value:
Możemy napisać tę funkcję od nowa w taki sposób, że będzie zwracała takie samo `this` z wartością `undefined`:

```js run
function makeUser(){
return this; // this time there's no object literal
return this; // tym razem nie jest zwracany obiekt
}

alert( makeUser().name ); // Error: Cannot read property 'name' of undefined
```
As you can see the result of `alert( makeUser().name )` is the same as the result of `alert( user.ref.name )` from the previous example.
Jak widzisz wynik `alert( makeUser().name )` jest taki sam jak wynik `alert( user.ref.name )` z poprzedniego przykładu.

Here's the opposite case:
A tutaj odwrotna sytuacja:

```js run
function makeUser() {
Expand All @@ -52,4 +52,4 @@ let user = makeUser();
alert( user.ref().name ); // John
```

Now it works, because `user.ref()` is a method. And the value of `this` is set to the object before dot `.`.
Teraz kod działa prawidłowo, ponieważ `user.ref()` jest metodą, a wartością `this` jest obiekt przed kropką `.`.
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ importance: 5

---

# Using "this" in object literal
# "this" w obiektach

Here the function `makeUser` returns an object.
Poniższa funkcja `makeUser` zwraca obiekt.

What is the result of accessing its `ref`? Why?
Jaki będzie rezultat dostępu do jego `ref`? I dlaczego?

```js
function makeUser() {
Expand All @@ -18,6 +18,6 @@ function makeUser() {

let user = makeUser();

alert( user.ref.name ); // What's the result?
alert( user.ref.name ); // Jaki będzie wynik?
```

12 changes: 6 additions & 6 deletions 1-js/04-object-basics/04-object-methods/7-calculator/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ importance: 5

---

# Create a calculator
# Stwórz kalkulator

Create an object `calculator` with three methods:
Stwórz obiekt `calculator` z trzema metodami:

- `read()` prompts for two values and saves them as object properties.
- `sum()` returns the sum of saved values.
- `mul()` multiplies saved values and returns the result.
- `read()` pobiera dwie wartości z okienek dialogowych `prompt` i zachowuje je jako właściwości obiektu.
- `sum()` zwraca sumę zachowanych wartości.
- `mul()` mnoży zachowane wartości i zwraca wynik.

```js
let calculator = {
// ... your code ...
// ... twój kod ...
};

calculator.read();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The solution is to return the object itself from every call.
Rozwiązaniem jest zwracanie obiektu z każdej funkcji.

```js run demo
let ladder = {
Expand Down Expand Up @@ -26,7 +26,7 @@ let ladder = {
ladder.up().up().down().up().down().showStep(); // 1
```

We also can write a single call per line. For long chains it's more readable:
Przy długich łańcuchach kodu, możemy każdy człon umieszczać w osobnej linijce, dla zwiększenia czytelności:

```js
ladder
Expand Down
12 changes: 6 additions & 6 deletions 1-js/04-object-basics/04-object-methods/8-chain-calls/task.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ importance: 2

---

# Chaining
# Łączenie

There's a `ladder` object that allows to go up and down:
Mamy tutaj obiekt `ladder` który pozwala wspinać się do góry i schodzić w dół:

```js
let ladder = {
Expand All @@ -15,13 +15,13 @@ let ladder = {
down() {
this.step--;
},
showStep: function() { // shows the current step
showStep: function() { // pokazuje aktualną wartość step
alert( this.step );
}
};
```

Now, if we need to make several calls in sequence, can do it like this:
Jeśli chcielibyśmy wykonać sekwencję ruchów, możemy zrobić to w ten sposób:

```js
ladder.up();
Expand All @@ -30,10 +30,10 @@ ladder.down();
ladder.showStep(); // 1
```

Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:
Zmodyfkuj kod dla `up`, `down` i `showStep` żeby można było połączyć wywołania metod, w taki sposób:

```js
ladder.up().up().down().showStep(); // 1
```

Such approach is widely used across JavaScript libraries.
Wiele bibliotek JavaScript wykorzystuje taki sposób pisania kodu.
Loading