diff --git a/1-js/5-data-types/08-keys-values-entries/article.md b/1-js/5-data-types/08-keys-values-entries/article.md index a6f20a03..259f7e6a 100644 --- a/1-js/5-data-types/08-keys-values-entries/article.md +++ b/1-js/5-data-types/08-keys-values-entries/article.md @@ -1,23 +1,23 @@ # Object.keys, values, entries +Let's step away from the indivitual data structures and talk about the iterations over them. + In the previous chapter we saw methods `map.keys()`, `map.values()`, `map.entries()`. -These methods are generic, there is a common agreement to use them for data structures. +These methods are generic, there is a common agreement to use them for data structures. If we ever create a data structure of our own, we should implement them too. They are supported for: - `Map` - `Set` -- `Array` (without `arr.values()`, because that would be repeating itself) +- `Array` (except `arr.values()`) -If we ever create a data structure of our own, we should implement them too. +Plain objects also support similar methods, but the syntax is a bit different. ## Object.keys, values, entries -For plain objects, situation is a little bit different. - -There are similar methods: +For plain objects, the following methods are available: - [Object.keys(obj)](mdn:js/Object/keys) -- returns an array of keys. - [Object.values(obj)](mdn:js/Object/values) -- returns an array of values. @@ -30,8 +30,11 @@ There are similar methods: | Call syntax | `map.keys()` | `Object.keys(obj)`, but not `obj.keys()` | | Returns | iterable | "real" Array | -1. The reason for call syntax `Object.keys(obj)` is flexibility. We can have an object of our own like `order` that implements its own `order.values()` method. And we still can call `Object.values(order)` on it. -2. ...And the returned value is not just an iterable, but an Array for historical reasons. +The first difference is that we have to call `Object.keys(obj)`, and not `obj.keys()`. + +Why so? There main reason is flexibility. Remember, objects are a base of all complex structures in Javascript. So we may have an object of our own like `order` that implements its own `order.values()` method. And we still can call `Object.values(order)` on it. + +The second difference is that `Object.*` methods return "real" array objects, not just an iterable. That's mainly for historical reasons. For instance: @@ -46,7 +49,7 @@ let user = { - `Object.values(user) = ["John", 30]` - `Object.entries(user) = [ ["name","John"], ["age",30] ]` -We can also `Object.values` for a loop over property values: +Here's an example of using `Object.values` to loop over property values: ```js run let user = { @@ -63,5 +66,5 @@ for(let value of Object.values(user)) { ```smart header="`Object.keys/values/entries` ignore symbolic properties" Just like `for..in` loop, these methods ignore properties that use `Symbol(...)` as keys. -Usually that's convenient. There is a separate method named [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys (if we really know what we're doing). Also, the method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) returns *all* keys. +Usually that's convenient. But if we want symbolic keys too, then there's a separate method [Object.getOwnPropertySymbols](mdn:js/Object/getOwnPropertySymbols) that returns an array of only symbolic keys. Also, the method [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) returns *all* keys. ``` diff --git a/1-js/5-data-types/09-destructuring-assignment/article.md b/1-js/5-data-types/09-destructuring-assignment/article.md index 11c8cd19..d043351d 100644 --- a/1-js/5-data-types/09-destructuring-assignment/article.md +++ b/1-js/5-data-types/09-destructuring-assignment/article.md @@ -1,6 +1,10 @@ # Destructuring assignment -*Destructuring assignment* is a special syntax that allows to "unpack" arrays or objects into a bunch of variables, that are sometimes more convenient to work. Destructuring also works great with complex functions that have a lot of parameters, default values etc. +The two most used data structures in Javascript are `Object` and `Array`. + +Objects allow to pack many pieces of information into a single entity and arrays allow to store ordered collections. So we can make an object or an array and handle it as a single thing, maybe pass to a function call. + +*Destructuring assignment* is a special syntax that allows to "unpack" arrays or objects into a bunch of variables, as sometimes they are more convenient. Destructuring also works great with complex functions that have a lot of parameters, default values, and soon we'll see how these are handled too. [cut] @@ -94,7 +98,9 @@ let user = { }; // loop over keys-and-values +*!* for(let [key, value] of Object.entries(user)) { +*/!* alert(`${key}:${value}`); // name:John, then age:30 } ``` @@ -106,7 +112,9 @@ let user = new Map(); user.set("name", "John"); user.set("age", "30"); +*!* for(let [key, value] of user.entries()) { +*/!* alert(`${key}:${value}`); // name:John, then age:30 } ``` diff --git a/1-js/8-more-functions/05-function-object/article.md b/1-js/8-more-functions/05-function-object/article.md index 1c754ff3..8657ceed 100644 --- a/1-js/8-more-functions/05-function-object/article.md +++ b/1-js/8-more-functions/05-function-object/article.md @@ -330,8 +330,8 @@ Now it works, because the name `"func"` is function-local. It is not taken from The outer code still has it's variable `sayHi` or `welcome` later. And `func` is an "internal function name", how it calls itself privately. -```smart header="No such thing for Function Declaration" -The "internal name" feature described here is only available for Function Expressions, not to Function Declarations. For Function Declarations, there's just no syntax possibility to add a one more "internal" name for them. +```smart header="There's no such thing for Function Declaration" +The "internal name" feature described here is only available for Function Expressions, not to Function Declarations. For Function Declarations, there's just no syntax possibility to add a one more "internal" name. Sometimes, when we need a reliable internal name, it's the reason to rewrite a Function Declaration to Named Function Expression form. ``` diff --git a/1-js/9-object-inheritance/04-function-prototype/article.md b/1-js/9-object-inheritance/04-function-prototype/article.md index 24e952b0..3cdf4f19 100644 --- a/1-js/9-object-inheritance/04-function-prototype/article.md +++ b/1-js/9-object-inheritance/04-function-prototype/article.md @@ -46,6 +46,99 @@ That's the resulting picture: On the picture, `"prototype"` is a horizontal arrow, it's a regular property, and `[[Prototype]]` is vertical, meaning the inheritance of `rabbit` from `animal`. + +## Default F.prototype, constructor property + +Every function has the `"prototype"` property even if we don't supply it. + +The default `"prototype"` is an object with the only property `constructor` that points back to the function itself. + +Like this: + +```js +function Rabbit() {} + +/* default prototype +Rabbit.prototype = { constructor: Rabbit }; +*/ +``` + + + +We can check it: + +```js run +function Rabbit() {} +// by default: +// Rabbit.prototype = { constructor: Rabbit } + +alert( Rabbit.prototype.constructor == Rabbit ); // true +``` + +Naturally, it we do nothing, the `constructor` property is available to all rabbits through `[[Prototype]]`: + +```js run +function Rabbit() {} +// by default: +// Rabbit.prototype = { constructor: Rabbit } + +let rabbit = new Rabbit(); // inherits from {constructor: Rabbit} + +alert(rabbit.constructor == Rabbit); // true (from prototype) +``` + + + +We can use `constructor` to create a new object using the same constructor as the existing one. + +Like here: + +```js run +function Rabbit(name) { + this.name = name; + alert(name); +} + +let rabbit = new Rabbit("White Rabbit"); + +let rabbit2 = new rabbit.constructor("Black Rabbit"); +``` + +That's handy when we have an object, don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create the same. + +...But probably the most important thing about `"constructor"` is that... + +**JavaScript itself does not use the `"constructor"` property at all.** + +Yes, it exists in the default `"prototype"` for functions, but that's literally all about it. No language function relies on it and nothing controls its validity. + +It is created automatically, but what happens with it later -- is totally on us. + +In particular, if we replace the default prototype by assigning our own `Rabbit.prototype = { jumps: true }`, then there will be no `"constructor"` in it. + +Such assignment won't break native methods or syntax, because nothing in the language uses the `"constructor"` property. But we may want to keep `"constructor"` for convenience by adding properties to the default `"prototype"` instead of overwriting it as a whole: + +```js +function Rabbit() {} + +// Not overwrite Rabbit.prototype totally +// just add to it +Rabbit.prototype.jumps = true +// the default Rabbit.prototype.constructor is preserved +``` + +Or, alternatively, recreate it manually: + +```js +Rabbit.prototype = { + jumps: true, +*!* + constructor: Rabbit +*/!* +}; +``` + + ## Summary In this chapter we briefly described the way of setting a `[[Prototype]]` for objects created via a constructor function. Later we'll see more advanced programming patterns that rely on it. @@ -64,3 +157,5 @@ let user = { prototype: "Bla-bla" // no magic at all }; ``` + +By default all functions have `F.prototype = { constructor: F }`. So by default we can get the constructor of an object by accessing its `"constructor"` property. diff --git a/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor.png b/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor.png index 915e42c7..0dbc7b8f 100644 Binary files a/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor.png and b/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor.png differ diff --git a/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor@2x.png b/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor@2x.png index fedf2111..e38cb85b 100644 Binary files a/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor@2x.png and b/1-js/9-object-inheritance/04-function-prototype/function-prototype-constructor@2x.png differ diff --git a/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor.png b/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor.png index a28dd6a3..9c0b2235 100644 Binary files a/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor.png and b/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor.png differ diff --git a/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor@2x.png b/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor@2x.png index 62991735..76879338 100644 Binary files a/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor@2x.png and b/1-js/9-object-inheritance/04-function-prototype/rabbit-prototype-constructor@2x.png differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/1-defer-to-prototype/solution.md b/1-js/9-object-inheritance/05-native-prototypes/1-defer-to-prototype/solution.md similarity index 100% rename from 1-js/9-object-inheritance/06-native-prototypes/1-defer-to-prototype/solution.md rename to 1-js/9-object-inheritance/05-native-prototypes/1-defer-to-prototype/solution.md diff --git a/1-js/9-object-inheritance/06-native-prototypes/1-defer-to-prototype/task.md b/1-js/9-object-inheritance/05-native-prototypes/1-defer-to-prototype/task.md similarity index 100% rename from 1-js/9-object-inheritance/06-native-prototypes/1-defer-to-prototype/task.md rename to 1-js/9-object-inheritance/05-native-prototypes/1-defer-to-prototype/task.md diff --git a/1-js/9-object-inheritance/06-native-prototypes/2-defer-to-prototype-extended/solution.md b/1-js/9-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md similarity index 100% rename from 1-js/9-object-inheritance/06-native-prototypes/2-defer-to-prototype-extended/solution.md rename to 1-js/9-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/solution.md diff --git a/1-js/9-object-inheritance/06-native-prototypes/2-defer-to-prototype-extended/task.md b/1-js/9-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/task.md similarity index 100% rename from 1-js/9-object-inheritance/06-native-prototypes/2-defer-to-prototype-extended/task.md rename to 1-js/9-object-inheritance/05-native-prototypes/2-defer-to-prototype-extended/task.md diff --git a/1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/solution.md b/1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/solution.md similarity index 94% rename from 1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/solution.md rename to 1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/solution.md index ba0fb4eb..02e07b8f 100644 --- a/1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/solution.md +++ b/1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/solution.md @@ -19,7 +19,7 @@ dictionary.__proto__ = "test"; // apple and __proto__ is in the loop for(let key in dictionary) { - alert(key); // "apple", then "__proto" + alert(key); // "apple", then "__proto__" } // comma-separated list of properties by toString diff --git a/1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/task.md b/1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/task.md similarity index 66% rename from 1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/task.md rename to 1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/task.md index d76ab231..039bc0ea 100644 --- a/1-js/9-object-inheritance/05-object-prototype/2-dictionary-tostring/task.md +++ b/1-js/9-object-inheritance/05-native-prototypes/2-dictionary-tostring/task.md @@ -6,24 +6,27 @@ importance: 5 There's an object `dictionary`, suited to store any `key/value` pairs. -Add `toString` for it, that would show a list of comma-delimited keys. The method itself should not show up in `for..in` over the object. +Add `toString` for it, that would show a list of comma-delimited keys. Your `toString` should not show up in `for..in` over the object. Here's how it should work: ```js let dictionary = Object.create(null); +*!* // your code to add toString +*/!* +// add some data dictionary.apple = "Apple"; dictionary.__proto__ = "test"; -// apple and __proto__ is in the loop +// only apple and __proto__ are in the loop for(let key in dictionary) { - alert(key); // "apple", then "__proto" + alert(key); // "apple", then "__proto__" } -// comma-separated list of properties by toString +// your toString in action alert(dictionary); // "apple,__proto__" ``` diff --git a/1-js/9-object-inheritance/05-object-prototype/3-compare-calls/solution.md b/1-js/9-object-inheritance/05-native-prototypes/3-compare-calls/solution.md similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/3-compare-calls/solution.md rename to 1-js/9-object-inheritance/05-native-prototypes/3-compare-calls/solution.md diff --git a/1-js/9-object-inheritance/05-object-prototype/3-compare-calls/task.md b/1-js/9-object-inheritance/05-native-prototypes/3-compare-calls/task.md similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/3-compare-calls/task.md rename to 1-js/9-object-inheritance/05-native-prototypes/3-compare-calls/task.md diff --git a/1-js/9-object-inheritance/07-constructor-property/4-new-object-same-constructor/solution.md b/1-js/9-object-inheritance/05-native-prototypes/4-new-object-same-constructor/solution.md similarity index 87% rename from 1-js/9-object-inheritance/07-constructor-property/4-new-object-same-constructor/solution.md rename to 1-js/9-object-inheritance/05-native-prototypes/4-new-object-same-constructor/solution.md index e85f32a3..43190e16 100644 --- a/1-js/9-object-inheritance/07-constructor-property/4-new-object-same-constructor/solution.md +++ b/1-js/9-object-inheritance/05-native-prototypes/4-new-object-same-constructor/solution.md @@ -39,6 +39,6 @@ Here's how `new user.constructor('Pete')` works: 1. First, it looks for `constructor` in `user`. Nothing. 2. Then it follows the prototype chain. The prototype of `user` is `User.prototype`, and it also has nothing. -3. The value of `User.prototype` is a plain object `{}`, it's prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used. +3. The value of `User.prototype` is a plain object `{}`, its prototype is `Object.prototype`. And there is `Object.prototype.constructor == Object`. So it is used. At the end, we have `let user2 = new Object('Pete')`. The built-in `Object` constructor ignores arguments, it always creates an empty object -- that's what we have in `user2` after all. diff --git a/1-js/9-object-inheritance/07-constructor-property/4-new-object-same-constructor/task.md b/1-js/9-object-inheritance/05-native-prototypes/4-new-object-same-constructor/task.md similarity index 100% rename from 1-js/9-object-inheritance/07-constructor-property/4-new-object-same-constructor/task.md rename to 1-js/9-object-inheritance/05-native-prototypes/4-new-object-same-constructor/task.md diff --git a/1-js/9-object-inheritance/06-native-prototypes/article.md b/1-js/9-object-inheritance/05-native-prototypes/article.md similarity index 77% rename from 1-js/9-object-inheritance/06-native-prototypes/article.md rename to 1-js/9-object-inheritance/05-native-prototypes/article.md index 11ae94b0..8cc56eb8 100644 --- a/1-js/9-object-inheritance/06-native-prototypes/article.md +++ b/1-js/9-object-inheritance/05-native-prototypes/article.md @@ -1,14 +1,55 @@ - # Native prototypes -All built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes. +The `"prototype"` property is widely used by the core of Javascript itself. All built-in constructor functions use it. -For instance, when we create an array, `[1, 2, 3]`, the default `new Array()` constructor is used internally. So the array data is written into the new object, and `Array.prototype` becomes its prototype and provides methods. That's very memory-efficient. +We'll see how it is for plain objects first, and then for more complex ones. + +## Object.prototype + +Let's say we output an empty object: + +```js run +let obj = {}; +alert( obj ); // "[object Object]" ? +``` + +Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty! + +...But the short notation `obj = {}` is the same as `obj = new Object()`, where `Object` -- is a built-in object constructor function. And that function has `Object.prototype` that references a huge object with `toString` and other functions. + +Like this (all that is built-in): + + + +When `new Object()` is called (or a literal object `{...}` is created), the `[[Prototype]]` of it is set to `Object.prototype` by the rule that we've discussed in the previous chapter: + + + +Afterwards when `obj.toString()` is called -- the method is taken from `Object.prototype`. + +We can check it like this: + +```js run +let obj = {}; + +alert(obj.__proto__ === Object.prototype); // true +// obj.toString === obj.__proto__toString == Object.prototype.toString +``` + +Please note that there is no additional `[[Prototype]]` in the chain above `Object.prototype`: + +```js run +alert(Object.prototype.__proto__); // null +``` + +## Other built-in prototypes + +Other built-in objects such as `Array`, `Date`, `Function` and others also keep methods in prototypes. + +For instance, when we create an array `[1, 2, 3]`, the default `new Array()` constructor is used internally. So the array data is written into the new object, and `Array.prototype` becomes its prototype and provides methods. That's very memory-efficient. By specification, all built-in prototypes have `Object.prototype` on the top. Sometimes people say that "everything inherits from objects". -[cut] - Here's the overall picture (for 3 built-ins to fit):  diff --git a/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor.png b/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor.png new file mode 100644 index 00000000..0dbc7b8f Binary files /dev/null and b/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor.png differ diff --git a/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor@2x.png b/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor@2x.png new file mode 100644 index 00000000..e38cb85b Binary files /dev/null and b/1-js/9-object-inheritance/05-native-prototypes/function-prototype-constructor@2x.png differ diff --git a/1-js/9-object-inheritance/05-object-prototype/native-prototypes-array-tostring.png b/1-js/9-object-inheritance/05-native-prototypes/native-prototypes-array-tostring.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/native-prototypes-array-tostring.png rename to 1-js/9-object-inheritance/05-native-prototypes/native-prototypes-array-tostring.png diff --git a/1-js/9-object-inheritance/05-object-prototype/native-prototypes-array-tostring@2x.png b/1-js/9-object-inheritance/05-native-prototypes/native-prototypes-array-tostring@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/native-prototypes-array-tostring@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/native-prototypes-array-tostring@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/native-prototypes-classes.png b/1-js/9-object-inheritance/05-native-prototypes/native-prototypes-classes.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/native-prototypes-classes.png rename to 1-js/9-object-inheritance/05-native-prototypes/native-prototypes-classes.png diff --git a/1-js/9-object-inheritance/05-object-prototype/native-prototypes-classes@2x.png b/1-js/9-object-inheritance/05-native-prototypes/native-prototypes-classes@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/native-prototypes-classes@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/native-prototypes-classes@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-1.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-1.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-1.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-1.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-1@2x.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-1@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-1@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-1@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-2.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-2.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-2.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-2.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-2@2x.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-2@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-2@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-2@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-null.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-null.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-null.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-null.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype-null@2x.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype-null@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype-null@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype-null@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype.png diff --git a/1-js/9-object-inheritance/05-object-prototype/object-prototype@2x.png b/1-js/9-object-inheritance/05-native-prototypes/object-prototype@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/object-prototype@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/object-prototype@2x.png diff --git a/1-js/9-object-inheritance/05-object-prototype/proto-constructor-animal-rabbit.png b/1-js/9-object-inheritance/05-native-prototypes/proto-constructor-animal-rabbit.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/proto-constructor-animal-rabbit.png rename to 1-js/9-object-inheritance/05-native-prototypes/proto-constructor-animal-rabbit.png diff --git a/1-js/9-object-inheritance/05-object-prototype/proto-constructor-animal-rabbit@2x.png b/1-js/9-object-inheritance/05-native-prototypes/proto-constructor-animal-rabbit@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/proto-constructor-animal-rabbit@2x.png rename to 1-js/9-object-inheritance/05-native-prototypes/proto-constructor-animal-rabbit@2x.png diff --git a/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor.png b/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor.png new file mode 100644 index 00000000..9c0b2235 Binary files /dev/null and b/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor.png differ diff --git a/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor@2x.png b/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor@2x.png new file mode 100644 index 00000000..76879338 Binary files /dev/null and b/1-js/9-object-inheritance/05-native-prototypes/rabbit-prototype-constructor@2x.png differ diff --git a/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor.png b/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor.png deleted file mode 100644 index 915e42c7..00000000 Binary files a/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor.png and /dev/null differ diff --git a/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor@2x.png b/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor@2x.png deleted file mode 100644 index fedf2111..00000000 Binary files a/1-js/9-object-inheritance/05-object-prototype/function-prototype-constructor@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor.png b/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor.png deleted file mode 100644 index a28dd6a3..00000000 Binary files a/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor.png and /dev/null differ diff --git a/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor@2x.png b/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor@2x.png deleted file mode 100644 index 62991735..00000000 Binary files a/1-js/9-object-inheritance/05-object-prototype/rabbit-prototype-constructor@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototype-object.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototype-object.png deleted file mode 100644 index 1353bd9c..00000000 --- a/1-js/9-object-inheritance/06-native-prototypes/native-prototype-object.png +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring.png deleted file mode 100644 index 83258d06..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring@2x.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring@2x.png deleted file mode 100644 index d77cc8f4..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-array-tostring@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes.png deleted file mode 100644 index fa6a2943..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes@2x.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes@2x.png deleted file mode 100644 index 9368d7e5..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-classes@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object.png deleted file mode 100644 index 87479a17..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object.png and /dev/null differ diff --git a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object@2x.png b/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object@2x.png deleted file mode 100644 index de8b7dc6..00000000 Binary files a/1-js/9-object-inheritance/06-native-prototypes/native-prototypes-object@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/05-object-prototype/article.md b/1-js/9-object-inheritance/06-prototype-methods/article.md similarity index 80% rename from 1-js/9-object-inheritance/05-object-prototype/article.md rename to 1-js/9-object-inheritance/06-prototype-methods/article.md index fc6801cc..0643798c 100644 --- a/1-js/9-object-inheritance/05-object-prototype/article.md +++ b/1-js/9-object-inheritance/06-prototype-methods/article.md @@ -1,106 +1,5 @@ -# Object.prototype and methods -The `"prototype"` property is widely used by the core of Javascript itself. All built-in constructor functions use it. - -We'll see how it is for plain objects first, and then for more complex ones. - -Let's say we output an empty object: - -```js run -let obj = {}; -alert( obj ); // "[object Object]" ? -``` - -Where's the code that generates the string `"[object Object]"`? That's a built-in `toString` method, but where is it? The `obj` is empty! - -...But the short notation `obj = {}` is the same as `obj = new Object()`, where `Object` -- is a built-in object constructor function. And that function has `Object.prototype` that references a huge object with `toString` and other functions. - -Like this (all that is built-in): - - - -When `new Object()` is called (or a literal object `{...}` is created), the `[[Prototype]]` of it is set to `Object.prototype` by the rule that we've discussed in the previous chapter: - - - -Afterwards when `obj.toString()` is called -- the method is taken from `Object.prototype`. - -We can check it like this: - -```js run -let obj = {}; - -alert(obj.__proto__ === Object.prototype); // true -// obj.toString === obj.__proto__toString == Object.prototype.toString -``` - -Please note that there is no additional `[[Prototype]]` in the chain above `Object.prototype`: - -```js run -alert(Object.prototype.__proto__); // null -``` - -## Getting all properties - -There are many ways to get keys/values from an object: - -- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames) -- returns an array of all own string property names. -- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic property names. -- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs. - -All of them operate on the object itself. But `for..in` loop is different: it also gives inherited properties. - -For instance: - -```js run -let animal = { - eats: true -}; - -let rabbit = { - jumps: true, - __proto__: animal -}; - -*!* -// only own keys -alert(Object.keys(rabbit)); // jumps -*/!* - -*!* -// inherited keys too -for(let prop in rabbit) alert(prop); // jumps, then eats -*/!* -``` - -If we want to differ inherited properties, there's a built-in method [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`. - -So we can filter out inherited properties (or do something else with them): - -```js run -let animal = { - eats: true -}; - -let rabbit = { - jumps: true, - __proto__: animal -}; - -for(let prop in rabbit) { - let isOwn = rabbit.hasOwnProperty(prop); - alert(`${prop}: ${isOwn}`); // jumps:true, then eats:false -} -``` -Here we have the following inheritance chain: `rabbit`, then `animal`, then `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it: - - - -So when `rabbit.hasOwnProperty` is called, the method `hasOwnProperty` is taken from `Object.prototype`. Why `hasOwnProperty` itself does not appear in `for..in` loop? The answer is simple: it's not enumerable just like all other properties of `Object.prototype`. - -As a take-away, let's remember that if we want inherited properties -- we should use `for..in`, and otherwise we can use other iteration methods or add the `hasOwnProperty` check. - -## Prototype setters and getters +# Methods for prototypes There are also other ways to get/set a prototype, besides those that we already know: @@ -108,6 +7,7 @@ There are also other ways to get/set a prototype, besides those that we already - [Object.getPrototypeOf(obj)](mdn:js/Object.getPrototypeOf) -- returns the `[[Prototype]]` of `obj`. - [Object.setPrototypeOf(obj, proto)](mdn:js/Object.setPrototypeOf) -- sets the `[[Prototype]]` of `obj` to `proto`. +[cut] For instance: @@ -236,13 +136,86 @@ chineseDictionary.bye = "zai jian"; alert(Object.keys(chineseDictionary)); // hello,bye ``` +## Getting all properties -## Summary +There are many ways to get keys/values from an object. + +We already know these ones: + +- [Object.keys(obj)](mdn:js/Object/keys) / [Object.values(obj)](mdn:js/Object/values) / [Object.entries(obj)](mdn:js/Object/entries) -- returns an array of enumerable own string property names/values/key-value pairs. + +These methods only list *enumerable* properties, and those that have *strings as keys*. + +If we want symbolic properties: + +- [Object.getOwnPropertySymbols(obj)](mdn:js/Object/getOwnPropertySymbols) -- returns an array of all own symbolic property names. + +If we want non-enumerable properties: + +- [Object.getOwnPropertyNames(obj)](mdn:js/Object/getOwnPropertyNames) -- returns an array of all own string property names. + +If we want *everything*: + +- [Reflect.ownKeys(obj)](mdn:js/Reflect/ownKeys) -- returns an array of all own property names. + +All of them operate on the object itself. Properties from the prototype are not listed. + +But `for..in` loop is different: it also gives inherited properties. + +For instance: + +```js run +let animal = { + eats: true +}; + +let rabbit = { + jumps: true, + __proto__: animal +}; + +*!* +// only own keys +alert(Object.keys(rabbit)); // jumps +*/!* + +*!* +// inherited keys too +for(let prop in rabbit) alert(prop); // jumps, then eats +*/!* +``` + +If we want to distinguish inherited properties, there's a built-in method [obj.hasOwnProperty(key)](mdn:js/Object/hasOwnProperty): it returns `true` if `obj` has its own (not inherited) property named `key`. + +So we can filter out inherited properties (or do something else with them): + +```js run +let animal = { + eats: true +}; + +let rabbit = { + jumps: true, + __proto__: animal +}; + +for(let prop in rabbit) { + let isOwn = rabbit.hasOwnProperty(prop); + alert(`${prop}: ${isOwn}`); // jumps:true, then eats:false +} +``` +Here we have the following inheritance chain: `rabbit`, then `animal`, then `Object.prototype` (because `animal` is a literal object `{...}`, so it's by default), and then `null` above it: + + + +So when `rabbit.hasOwnProperty` is called, the method `hasOwnProperty` is taken from `Object.prototype`. Why `hasOwnProperty` itself does not appear in `for..in` loop? The answer is simple: it's not enumerable just like all other properties of `Object.prototype`. + +As a take-away, let's remember that if we want inherited properties -- we should use `for..in`, and otherwise we can use other iteration methods or add the `hasOwnProperty` check. + +## Summary [todo] The `"prototype"` property of constructor functions is essential for Javascript built-in methods. In this chapter we saw how it works for objects: -- - In the next chapter we'll see the bigger picture: how other built-ins rely on it to inherit from each other. diff --git a/1-js/9-object-inheritance/05-object-prototype/rabbit-animal-object.png b/1-js/9-object-inheritance/06-prototype-methods/rabbit-animal-object.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/rabbit-animal-object.png rename to 1-js/9-object-inheritance/06-prototype-methods/rabbit-animal-object.png diff --git a/1-js/9-object-inheritance/05-object-prototype/rabbit-animal-object@2x.png b/1-js/9-object-inheritance/06-prototype-methods/rabbit-animal-object@2x.png similarity index 100% rename from 1-js/9-object-inheritance/05-object-prototype/rabbit-animal-object@2x.png rename to 1-js/9-object-inheritance/06-prototype-methods/rabbit-animal-object@2x.png diff --git a/1-js/9-object-inheritance/07-constructor-property/article.md b/1-js/9-object-inheritance/07-constructor-property/article.md deleted file mode 100644 index 30073da9..00000000 --- a/1-js/9-object-inheritance/07-constructor-property/article.md +++ /dev/null @@ -1,89 +0,0 @@ - -# The "constructor" property - -[todo make me more interesting] -Every function by default already has the `"prototype"` property. - -It's an object of this form: - -```js -function Rabbit() {} - -Rabbit.prototype = { - constructor: Rabbit -}; -``` - -Here, `Rabbit.prototype` is assigned manually, but the same object is its value by default. - -We can check it: - -```js -function Rabbit() {} -// Rabbit.prototype = { constructor: Rabbit } - -alert( Rabbit.prototype.constructor == Rabbit ); // true -``` - -Here's the picture: - - - -Naturally, the `"constructor"` property becomes available to all rabbits through the `[[Prototype]]`: - -```js run -function Rabbit() {} - -let rabbit = new Rabbit(); - -alert(rabbit.constructor == Rabbit); // true -``` - - - -We can use it to create a new object using the same constructor as the existing one: - -```js run -function Rabbit(name) { - this.name = name; - alert(name); -} - -let rabbit = new Rabbit("White Rabbit"); - -let rabbit2 = new rabbit.constructor("Black Rabbit"); -``` - -That may come in handy when we have an object, but don't know which constructor was used for it (e.g. it comes from a 3rd party library), and we need to create the same. - -Probably the most important thing about `"constructor"` is that... - -**JavaScript itself does not use the `"constructor"` property at all.** - -Yes, it exists in the default `"prototype"` for functions, but that's literally all about it. No language function relies on it and nothing controls its validity. - -It is created automatically, but what happens with it later -- is totally on us. - -In particular, if we assign our own `Rabbit.prototype = { jumps: true }`, then there will be no `"constructor"` in it any more. - -Such assignment won't break native methods or syntax, because nothing in the language uses the `"constructor"` property. But we may want to keep `"constructor"` for convenience or just in case, by adding properties to the default `"prototype"` instead of overwriting it as a whole: - -```js -function Rabbit() {} - -// Not overwrite Rabbit.prototype totally -// just add to it -Rabbit.prototype.jumps = true -// the default Rabbit.prototype.constructor is preserved -``` - -Or, alternatively, recreate it manually: - -```js -Rabbit.prototype = { - jumps: true, -*!* - constructor: Rabbit -*/!* -}; -``` diff --git a/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor.png b/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor.png deleted file mode 100644 index 915e42c7..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor@2x.png b/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor@2x.png deleted file mode 100644 index fedf2111..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/function-prototype-constructor@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring.png b/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring.png deleted file mode 100644 index 83258d06..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring@2x.png b/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring@2x.png deleted file mode 100644 index d77cc8f4..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-array-tostring@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes.png b/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes.png deleted file mode 100644 index fa6a2943..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes@2x.png b/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes@2x.png deleted file mode 100644 index 9368d7e5..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/native-prototypes-classes@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-1.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-1.png deleted file mode 100644 index c004d033..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-1.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-1@2x.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-1@2x.png deleted file mode 100644 index 16abecef..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-1@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-2.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-2.png deleted file mode 100644 index ee42f6b9..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-2.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-2@2x.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-2@2x.png deleted file mode 100644 index 1917c663..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-2@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-null.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-null.png deleted file mode 100644 index 7c2e3f9c..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-null.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype-null@2x.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype-null@2x.png deleted file mode 100644 index fec1facb..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype-null@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype.png deleted file mode 100644 index 390e7cd4..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/object-prototype@2x.png b/1-js/9-object-inheritance/07-constructor-property/object-prototype@2x.png deleted file mode 100644 index 2a10ef1e..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/object-prototype@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit.png b/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit.png deleted file mode 100644 index 3eec740f..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit@2x.png b/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit@2x.png deleted file mode 100644 index ed28a388..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/proto-constructor-animal-rabbit@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object.png b/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object.png deleted file mode 100644 index 3254270f..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object@2x.png b/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object@2x.png deleted file mode 100644 index f794d7b8..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/rabbit-animal-object@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor.png b/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor.png deleted file mode 100644 index a28dd6a3..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor.png and /dev/null differ diff --git a/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor@2x.png b/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor@2x.png deleted file mode 100644 index 62991735..00000000 Binary files a/1-js/9-object-inheritance/07-constructor-property/rabbit-prototype-constructor@2x.png and /dev/null differ diff --git a/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/solution.md b/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/solution.md new file mode 100644 index 00000000..55f945ca --- /dev/null +++ b/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/solution.md @@ -0,0 +1,46 @@ +Here's the line with the error: + +```js +Rabbit.prototype = Animal.prototype; +``` + +Here `Rabbit.prototype` and `Animal.prototype` become the same object. So methods of both classes become mixed in that object. + +As a result, `Rabbit.prototype.walk` overwrites `Animal.prototype.walk`, so all animals start to bounce: + +```js run +function Animal(name) { + this.name = name; +} + +Animal.prototype.walk = function() { + alert(this.name + ' walks'); +}; + +function Rabbit(name) { + this.name = name; +} + +*!* +Rabbit.prototype = Animal.prototype; +*/!* + +Rabbit.prototype.walk = function() { + alert(this.name + " bounces!"); +}; + +*!* +let animal = new Animal("pig"); +animal.walk(); // pig bounces! +*/!* +``` + +The correct variant would be: + +```js +Rabbit.prototype.__proto__ = Animal.prototype; +// or like this: +Rabbit.prototype = Object.create(Animal.prototype); +``` + +That makes prototypes separate, each of them stores methods of the corresponding class, but `Rabbit.prototype` inherits from `Animal.prototype`. diff --git a/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/task.md b/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/task.md new file mode 100644 index 00000000..ee486c3d --- /dev/null +++ b/1-js/9-object-inheritance/08-class-patterns/1-inheritance-error-assign/task.md @@ -0,0 +1,29 @@ +importance: 5 + +--- + +# An error in the inheritance + +Find an error in the prototypal inheritance below. + +What's wrong? What are consequences going to be? + +```js +function Animal(name) { + this.name = name; +} + +Animal.prototype.walk = function() { + alert(this.name + ' walks'); +}; + +function Rabbit(name) { + this.name = name; +} + +Rabbit.prototype = Animal.prototype; + +Rabbit.prototype.walk = function() { + alert(this.name + " bounces!"); +}; +``` diff --git a/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.md b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.md new file mode 100644 index 00000000..300b25d9 --- /dev/null +++ b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.md @@ -0,0 +1 @@ +Please note that properties that were internal in functional style (`template`, `timer`) and the internal method `render` are marked private with the underscore `_`. diff --git a/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js new file mode 100644 index 00000000..7a193b79 --- /dev/null +++ b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/clock.js @@ -0,0 +1,32 @@ +function Clock({ template }) { + this._template = template; +} + +Clock.prototype._render = function() { + let date = new Date(); + + let hours = date.getHours(); + if (hours < 10) hours = '0' + hours; + + let mins = date.getMinutes(); + if (mins < 10) min = '0' + mins; + + let secs = date.getSeconds(); + if (secs < 10) secs = '0' + secs; + + let output = this._template + .replace('h', hours) + .replace('m', mins) + .replace('s', secs); + + console.log(output); +}; + +Clock.prototype.stop = function() { + clearInterval(this._timer); +}; + +Clock.prototype.start = function() { + this._render(); + this._timer = setInterval(() => this._render(), 1000); +}; diff --git a/1-js/9-object-inheritance/10-class-inheritance/3-clock-class/solution.view/index.html b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html similarity index 57% rename from 1-js/9-object-inheritance/10-class-inheritance/3-clock-class/solution.view/index.html rename to 1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html index ec1acda9..fdee13d0 100644 --- a/1-js/9-object-inheritance/10-class-inheritance/3-clock-class/solution.view/index.html +++ b/1-js/9-object-inheritance/08-class-patterns/2-rewrite-to-prototypes/solution.view/index.html @@ -2,7 +2,7 @@
-