Skip to content

Object methods, "this" #52

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
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
**Error**!
**Eroare**!

Try it:
Incercați:

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

(user.go)() // error!
(user.go)() // eroare!
```

The error message in most browsers does not give understanding what went wrong.
Din mesajul de eroare furnizat de majoritatea browserelor nu reiese ce a mers prost.

**The error appears because a semicolon is missing after `user = {...}`.**
**Eroarea apare deoarece simbolul ";" lipsește după `user = {...}`.**

JavaScript does not auto-insert a semicolon before a bracket `(user.go)()`, so it reads the code like:
Limbajul JavaScript nu adaugă automat un simbol ";" înainte de paranteză `(user.go)()`, deci citește codul ca:

```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.
Apoi, putem vedea, de asemenea, că o astfel de expresie combinată este sintactic un apel al obiectului `{ go: ... }` ca funcție cu argumentul `(user.go)`. Și asta se întâmplă și pe aceeași linie cu `let user`, deci obiectul `user` nu a fost încă definit, de unde și eroarea.

If we insert the semicolon, all is fine:
Dacă introducem un simbol ";", totul este în regulă:

```js run
let user = {
@@ -34,4 +34,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.
Rețineți că parantezele din jurul `(user.go)` nu fac nimic aici. De obicei setează ordinea operațiilor, dar aici punctul `.` are oricum precedență, deci nu are niciun efect. Singurul lucru care contează este simbolul ";".
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@ importance: 2

---

# Syntax check
# Verificare de sintaxă

What is the result of this code?
Care este rezultatul următorului cod?


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

P.S. There's a pitfall :)
P.S. Există o capcană :)
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.
Iată explicațiile.

1. That's a regular object method call.
1. Aceasta este o apelare normală a metodei obiectului.

2. The same, brackets do not change the order of operations here, the dot is first anyway.
2. Similar, aici, parantezele nu schimbă ordinea operațiilor, punctul este oricum primul.

3. Here we have a more complex call `(expression).method()`. The call works as if it were split into two lines:
3. Aici avem un apel mai complex `(expression).method()`. Apelul funcționează ca și cum ar fi împărțit în două linii:

```js no-beautify
f = obj.go; // calculate the expression
f(); // call what we have
f = obj.go; // calculează expresia
f(); // apelează ce avem
```

Here `f()` is executed as a function, without `this`.
Aici `f()` este executat ca funcție, fără `this`.

4. The similar thing as `(3)`, to the left of the dot `.` we have an expression.
4. Similar cu `(3)`, la stânga punctului `.` avem o expresie.

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`.
Pentru a explica comportamentul apelurilor `(3)` și `(4)` trebuie să ne reamintim că accesorii de proprietăți (punct sau paranteze pătrate) returnează o valoare de Tip Referință.

Orice operație pe aceasta, cu excepția unui apel de metodă (precum alocarea `=` sau `||`) o transformă într-o valoare obișnuită, care nu poartă informațiile ce permit setarea variabilei `this`.
7 changes: 3 additions & 4 deletions 1-js/04-object-basics/04-object-methods/3-why-this/task.md
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@ importance: 3

---

# Explain the value of "this"
# Explicați valoarea variabilei "this"

In the code below we intend to call `user.go()` method 4 times in a row.
În codul următor intenționăm să apelăm metoda `user.go()` de 4 ori la rând.

But calls `(1)` and `(2)` works differently from `(3)` and `(4)`. Why?
Însă apelurile `(1)` și `(2)` funcționează diferit de `(3)` și `(4)`. De ce?

```js run no-beautify
let obj, method;
@@ -23,4 +23,3 @@ obj.go(); // (1) [object Object]

(obj.go || obj.stop)(); // (4) undefined
```

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
**Answer: an error.**
**Răspuns: o eroare.**

Try it:
Încercați:
```js run
function makeUser() {
return {
@@ -11,18 +11,18 @@ function makeUser() {

let user = makeUser();

alert( user.ref.name ); // Error: Cannot read property 'name' of undefined
alert( user.ref.name ); // Eroare: 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.
Acest lucru se datorează faptului că regulile care setează `this` nu se uită la definirea obiectului. Doar momentul apelului contează .

Here the value of `this` inside `makeUser()` is `undefined`, because it is called as a function, not as a method with "dot" syntax.
Aici valoarea variabilei `this` din interiorul funcției `makeUser()` este `undefined`, deoarece este apelată ca funcție, nu ca o metodă cu sintaxa "punct".

The value of `this` is one for the whole function, code blocks and object literals do not affect it.
Valoarea variabilei `this` este unică pentru întreaga funcția, blocurile de cod și obiectele literale nu o afectează.

So `ref: this` actually takes current `this` of the function.
În concluzie `ref: this` preia de fapt variabila curentă `this` a funcției.

Here's the opposite case:
Iată cazul opus:

```js run
function makeUser() {
@@ -41,4 +41,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 `.`.
Acum funcționează, pentru că `user.ref()` este o metodă. Iar valoarea variabilei `this` este setată la obiectul dinaintea punctului `.`.
Original file line number Diff line number Diff line change
@@ -2,11 +2,11 @@ importance: 5

---

# Using "this" in object literal
# Folosirea "this" în obiect literal

Here the function `makeUser` returns an object.
Aici funcția `makeUser` returnează un obiect.

What is the result of accessing its `ref`? Why?
Care este rezultatul accesării proprietății `ref`? De ce?

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

let user = makeUser();

alert( user.ref.name ); // What's the result?
alert( user.ref.name ); // Care este rezultatul?
```

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

---

# Create a calculator
# Creați un calculator

Create an object `calculator` with three methods:
Creați un obiect `calculator` cu trei metode:

- `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()` solicită două valori și le salvează ca proprietăți ale obiectului.
- `sum()` returnează suma valorilor salvate.
- `mul()` multiplică valorile salvate și returnează rezultatul.

```js
let calculator = {
// ... your code ...
// ... codul vostru ...
};

calculator.read();
@@ -21,4 +21,3 @@ alert( calculator.mul() );
```

[demo]

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.
Soluția este de a returna obiectul însuși la fiecare apelare.

```js run demo
let ladder = {
@@ -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:
De asemenea, putem scrie câte o apelare pe linie. Pentru înlănțuirile lungi este mai lizibil:

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

---

# Chaining
# Înlănțuirea

There's a `ladder` object that allows to go up and down:
Există un obiect `ladder` (scară) care permite urcarea și coborârea:

```js
let ladder = {
step: 0,
up() {
up() {
this.step++;
},
down() {
down() {
this.step--;
},
showStep: function() { // shows the current step
showStep: function() { // arată pasul curent
alert( this.step );
}
};
```

Now, if we need to make several calls in sequence, can do it like this:
În acest moment, dacă avem nevoie să facem mai multe apelări în ordine, le putem face astfel:

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

Modify the code of `up`, `down` and `showStep` to make the calls chainable, like this:
Modificați codul pentru `up`, `down` și `showStep` pentru a face apelările înlănțuibile, astfel:

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

Such approach is widely used across JavaScript libraries.
Asemenea abordare este utilizată pe scară largă în bibliotecile JavaScript.
222 changes: 111 additions & 111 deletions 1-js/04-object-basics/04-object-methods/article.md

Large diffs are not rendered by default.