Skip to content

Commit

Permalink
minor
Browse files Browse the repository at this point in the history
  • Loading branch information
iliakan committed Aug 4, 2019
1 parent 61bc426 commit 800d47c
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 23 deletions.
7 changes: 4 additions & 3 deletions 1-js/08-prototypes/04-prototype-methods/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ let rabbit = Object.create(animal);
*/!*

alert(rabbit.eats); // true

*!*
alert(Object.getPrototypeOf(rabbit) === animal); // get the prototype of rabbit
*/!*
Expand Down Expand Up @@ -78,7 +79,7 @@ As of now we have all these ways at our disposal.

Why was `__proto__` replaced by the functions `getPrototypeOf/setPrototypeOf`? That's an interesting question, requiring us to understand why `__proto__` is bad. Read on to get the answer.

```warn header="Don't reset `[[Prototype]]` unless the speed doesn't matter"
```warn header="Don't change `[[Prototype]]` on existing objects if speed matters"
Technically, we can get/set `[[Prototype]]` at any time. But usually we only set it once at the object creation time, and then do not modify: `rabbit` inherits from `animal`, and that is not going to change.

And JavaScript engines are highly optimized to that. Changing a prototype "on-the-fly" with `Object.setPrototypeOf` or `obj.__proto__=` is a very slow operation, it breaks internal optimizations for object property access operations. So evade it unless you know what you're doing, or JavaScript speed totally doesn't matter for you.
Expand Down Expand Up @@ -111,7 +112,7 @@ Here the consequences are not terrible. But in other cases, we may be assigning

What's worst -- usually developers do not think about such possibility at all. That makes such bugs hard to notice and even turn them into vulnerabilities, especially when JavaScript is used on server-side.

Unexpected things also may happen when accessing `toString` property -- that's a function by default, and other built-in properties.
Unexpected things also may happen when assigning to `toString` -- that's a function by default, and other built-in methods.

How to evade the problem?

Expand Down Expand Up @@ -160,7 +161,7 @@ alert(obj); // Error (no toString)

...But that's usually fine for associative arrays.

Please note that most object-related methods are `Object.something(...)`, like `Object.keys(obj)` -- they are not in the prototype, so they will keep working on such objects:
Note that most object-related methods are `Object.something(...)`, like `Object.keys(obj)` -- they are not in the prototype, so they will keep working on such objects:


```js run
Expand Down
28 changes: 15 additions & 13 deletions 1-js/09-classes/01-class/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class MyClass {
}
```

Then `new MyClass()` creates a new object with all the listed methods.
Then use `new MyClass()` to create a new object with all the listed methods.

The `constructor()` method is called automatically by `new`, so we can initialize the object there.

Expand Down Expand Up @@ -53,7 +53,7 @@ When `new User("John")` is called:
1. A new object is created.
2. The `constructor` runs with the given argument and assigns `this.name` to it.

...Then we can call methods, such as `user.sayHi`.
...Then we can call object methods, such as `user.sayHi()`.


```warn header="No comma between class methods"
Expand Down Expand Up @@ -191,7 +191,7 @@ let User = class {
};
```

Similar to Named Function Expressions, class expressions may or may not have a name.
Similar to Named Function Expressions, class expressions may have a name.

If a class expression has a name, it's visible inside the class only:
Expand All @@ -200,13 +200,13 @@ If a class expression has a name, it's visible inside the class only:
// (no such term in the spec, but that's similar to Named Function Expression)
let User = class *!*MyClass*/!* {
sayHi() {
alert(MyClass); // MyClass is visible only inside the class
alert(MyClass); // MyClass name is visible only inside the class
}
};

new User().sayHi(); // works, shows MyClass definition

alert(MyClass); // error, MyClass not visible outside of the class
alert(MyClass); // error, MyClass name isn't visible outside of the class
```


Expand Down Expand Up @@ -282,13 +282,14 @@ Object.defineProperties(User.prototype, {
});
```

Here's an example with computed properties:
Here's an example with a computed property in brackets `[...]`:

```js run
function f() { return "sayHi"; }

class User {
[f()]() {

*!*
['say' + 'Hi']() {
*/!*
alert("Hello");
}

Expand All @@ -309,7 +310,9 @@ In the example above, `User` only had methods. Let's add a property:

```js run
class User {
*!*
name = "Anonymous";
*/!*

sayHi() {
alert(`Hello, ${this.name}!`);
Expand All @@ -319,16 +322,15 @@ class User {
new User().sayHi();
```

The property is not placed into `User.prototype`. Instead, it is created by `new`, separately for every object. So, the property will never be shared between different objects of the same class.

The property `name` is not placed into `User.prototype`. Instead, it is created by `new` before calling constructor, it's the property of the object itself.

## Summary

The basic class syntax looks like this:

```js
class MyClass {
prop = value; // field
prop = value; // property

constructor(...) { // constructor
// ...
Expand All @@ -339,7 +341,7 @@ class MyClass {
get something(...) {} // getter method
set something(...) {} // setter method

[Symbol.iterator]() {} // method with computed name/symbol name
[Symbol.iterator]() {} // method with computed name (symbol here)
// ...
}
```
Expand Down
3 changes: 1 addition & 2 deletions 1-js/09-classes/02-class-inheritance/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Internally, `extends` keyword adds `[[Prototype]]` reference from `Rabbit.protot

So, if a method is not found in `Rabbit.prototype`, JavaScript takes it from `Animal.prototype`.

As we can recall from the chapter <info:native-prototypes>, JavaScript uses the same prototypal inheritance for build-in objects. E.g. `Date.prototype.[[Prototype]]` is `Object.prototype`, so dates have generic object methods.
As we can recall from the chapter <info:native-prototypes>, JavaScript uses prototypal inheritance for build-in objects. E.g. `Date.prototype.[[Prototype]]` is `Object.prototype`, so dates have generic object methods.

````smart header="Any expression is allowed after `extends`"
Class syntax allows to specify not just a class, but any expression after `extends`.
Expand Down Expand Up @@ -131,7 +131,6 @@ class Rabbit extends Animal {
}
```
...But usually we don't want to totally replace a parent method, but rather to build on top of it, tweak or extend its functionality. We do something in our method, but call the parent method before/after it or in the process.
Classes provide `"super"` keyword for that.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures.sketch
Binary file not shown.

0 comments on commit 800d47c

Please sign in to comment.