diff --git a/1-js/08-prototypes/04-prototype-methods/article.md b/1-js/08-prototypes/04-prototype-methods/article.md index 9ff71045..8a71dbf1 100644 --- a/1-js/08-prototypes/04-prototype-methods/article.md +++ b/1-js/08-prototypes/04-prototype-methods/article.md @@ -26,6 +26,7 @@ let rabbit = Object.create(animal); */!* alert(rabbit.eats); // true + *!* alert(Object.getPrototypeOf(rabbit) === animal); // get the prototype of rabbit */!* @@ -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. @@ -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? @@ -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 diff --git a/1-js/09-classes/01-class/article.md b/1-js/09-classes/01-class/article.md index cd6579c0..3cfcd4cb 100644 --- a/1-js/09-classes/01-class/article.md +++ b/1-js/09-classes/01-class/article.md @@ -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. @@ -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" @@ -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: @@ -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 ``` @@ -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"); } @@ -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}!`); @@ -319,8 +322,7 @@ 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 @@ -328,7 +330,7 @@ The basic class syntax looks like this: ```js class MyClass { - prop = value; // field + prop = value; // property constructor(...) { // constructor // ... @@ -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) // ... } ``` diff --git a/1-js/09-classes/02-class-inheritance/article.md b/1-js/09-classes/02-class-inheritance/article.md index 29d3188a..27ad9eeb 100644 --- a/1-js/09-classes/02-class-inheritance/article.md +++ b/1-js/09-classes/02-class-inheritance/article.md @@ -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 , 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 , 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`. @@ -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. diff --git a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg index 06af805f..580379ab 100644 --- a/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg +++ b/1-js/09-classes/02-class-inheritance/rabbit-animal-independent-animal.svg @@ -5,7 +5,7 @@ Created with sketchtool. - + constructor: Animal @@ -19,7 +19,7 @@ Animal - + new Animal diff --git a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg index b98f6bd1..7b508613 100644 --- a/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg +++ b/1-js/09-classes/03-static-properties-methods/animal-rabbit-static.svg @@ -5,16 +5,16 @@ Created with sketchtool. - + constructor: Animal run: function - + Animal.prototype - + constructor: Rabbit hide: function diff --git a/figures.sketch b/figures.sketch index 02fa5829..5f194036 100644 Binary files a/figures.sketch and b/figures.sketch differ