diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md index cb9829ce0..5138cb70f 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/solution.md @@ -1,14 +1,14 @@ -First, let's see why the latter code doesn't work. +Lad os først se på, hvorfor den sidste kode ikke virker. -The reason becomes obvious if we try to run it. An inheriting class constructor must call `super()`. Otherwise `"this"` won't be "defined". +Grunden til det bliver tydelig hvis vi prøver at køre den. En arvende klassekonstruktør skal kalde `super()`. Ellers vil `"this"` ikke være "defineret". -So here's the fix: +Så her er en måde at fixe det på: ```js run class Rabbit extends Object { constructor(name) { *!* - super(); // need to call the parent constructor when inheriting + super(); // du skal kalde den overordnede konstruktør når du nedarver */!* this.name = name; } @@ -19,16 +19,16 @@ let rabbit = new Rabbit("Rab"); alert( rabbit.hasOwnProperty('name') ); // true ``` -But that's not all yet. +Men det er ikke alt. -Even after the fix, there's still an important difference between `"class Rabbit extends Object"` and `class Rabbit`. +Selv efter denne rettelse er der en vigtig forskel mellem `"class Rabbit extends Object"` og `class Rabbit`. -As we know, the "extends" syntax sets up two prototypes: +Som vi ved, opretter "extends" syntaksen to prototyper: -1. Between `"prototype"` of the constructor functions (for methods). -2. Between the constructor functions themselves (for static methods). +1. Mellem `"prototype"` af constructor funktionerne (for metoder). +2. Mellem constructor funktionerne selv (for statiske metoder). -In the case of `class Rabbit extends Object` it means: +I tilfældet med `class Rabbit extends Object` betyder det, at `Rabbit` nedarver både de statiske og de normale metoder fra `Object`.: ```js run class Rabbit extends Object {} @@ -37,45 +37,45 @@ alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) true ``` -So `Rabbit` now provides access to the static methods of `Object` via `Rabbit`, like this: +Så `Rabbit` giver nu adgang til de statiske metoder fra `Object` via `Rabbit`, som dette: ```js run class Rabbit extends Object {} *!* -// normally we call Object.getOwnPropertyNames +// normalt kalder vi Object.getOwnPropertyNames alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // a,b */!* ``` -But if we don't have `extends Object`, then `Rabbit.__proto__` is not set to `Object`. +Men, hvis vi ikke har `extends Object` så bliver `Rabbit.__proto__` ikke sat til `Object`. -Here's the demo: +Her er en demonstration af dette: ```js run class Rabbit {} alert( Rabbit.prototype.__proto__ === Object.prototype ); // (1) true alert( Rabbit.__proto__ === Object ); // (2) false (!) -alert( Rabbit.__proto__ === Function.prototype ); // as any function by default +alert( Rabbit.__proto__ === Function.prototype ); // som enhver funktion som standard *!* -// error, no such function in Rabbit -alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Error +// fejl, sådan en funktion findes ikke i Rabbit +alert ( Rabbit.getOwnPropertyNames({a: 1, b: 2})); // Fejl */!* ``` -So `Rabbit` doesn't provide access to static methods of `Object` in that case. +Så `Rabbit` giver ikke adgang til de statiske metoder fra `Object` i det tilfælde. -By the way, `Function.prototype` also has "generic" function methods, like `call`, `bind` etc. They are ultimately available in both cases, because for the built-in `Object` constructor, `Object.__proto__ === Function.prototype`. +Forresten så har`Function.prototype` også en "generiske" function metoder, såsom `call`, `bind` osv. De er i sidste ende tilgængelige i begge tilfælde, fordi for den indbyggede `Object` constructor, `Object.__proto__ === Function.prototype`. -Here's the picture: +Her er en oversigt over forskellene: ![](rabbit-extends-object.svg) -So, to put it short, there are two differences: +Så, kort fortalt er der to forskelle: | class Rabbit | class Rabbit extends Object | |--------------|------------------------------| -| -- | needs to call `super()` in constructor | +| -- | skal kalde `super()` i constructor | | `Rabbit.__proto__ === Function.prototype` | `Rabbit.__proto__ === Object` | diff --git a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md index 1d0f98a74..874f1e752 100644 --- a/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md +++ b/1-js/09-classes/03-static-properties-methods/3-class-extend-object/task.md @@ -2,11 +2,11 @@ importance: 3 --- -# Class extends Object? +# Klasse udvider object? -As we know, all objects normally inherit from `Object.prototype` and get access to "generic" object methods like `hasOwnProperty` etc. +Som vi ved, nedarver alle objekter normalt fra `Object.prototype` og får dermed adgang til "generiske" objektmetoder som `hasOwnProperty` etc. -For instance: +For eksempel: ```js run class Rabbit { @@ -18,16 +18,16 @@ class Rabbit { let rabbit = new Rabbit("Rab"); *!* -// hasOwnProperty method is from Object.prototype +// hasOwnProperty metoden kommer fra Object.prototype alert( rabbit.hasOwnProperty('name') ); // true */!* ``` -But if we spell it out explicitly like `"class Rabbit extends Object"`, then the result would be different from a simple `"class Rabbit"`? +Men, hvis vi skriver det udtrykkeligt som `"class Rabbit extends Object"`, så vil resultatet være anderledes end ved en simpel `"class Rabbit"`? -What's the difference? +Hvad er forskellen? -Here's an example of such code (it doesn't work -- why? fix it?): +Her er et eksempel på sådan en kode (den virker ikke -- hvorfor? fix den?): ```js class Rabbit extends Object { @@ -38,5 +38,5 @@ class Rabbit extends Object { let rabbit = new Rabbit("Rab"); -alert( rabbit.hasOwnProperty('name') ); // Error +alert( rabbit.hasOwnProperty('name') ); // Fejl ``` 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 3e354b895..2bc92cf0d 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 @@ -1 +1,91 @@ -constructor: Animal run: functionAnimal.prototypeconstructor: Rabbit hide: functionRabbit.prototypeAnimalRabbitrabbit[[Prototype]][[Prototype]][[Prototype]]prototypeprototypecomparename: "White Rabbit" \ No newline at end of file + + + + + + + + + + + constructor: Animal + + run: function + + + + Animal.prototype + + + + constructor: Rabbit + + hide: function + + + Rabbit.prototype + + + + Animal + + + + Rabbit + + + rabbit + + + + + [[Prototype]] + + + + [[Prototype]] + + + + [[Prototype]] + + + prototype + + + + prototype + + + compare + + + name: "Hvid kanin" + + + + \ No newline at end of file diff --git a/1-js/09-classes/03-static-properties-methods/article.md b/1-js/09-classes/03-static-properties-methods/article.md index 4b493a5e8..3199257d5 100644 --- a/1-js/09-classes/03-static-properties-methods/article.md +++ b/1-js/09-classes/03-static-properties-methods/article.md @@ -1,9 +1,9 @@ -# Static properties and methods +# Statiske egenskaber og metoder -We can also assign a method to the class as a whole. Such methods are called *static*. +Vi kan også tildele en metode til selve klassen som sådan. Sådanne metoder kaldes *statiske metoder*. -In a class declaration, they are prepended by `static` keyword, like this: + en klasse-deklaration er de præfikseret med `static` nøgleordet, som her: ```js run class User { @@ -17,7 +17,7 @@ class User { User.staticMethod(); // true ``` -That actually does the same as assigning it as a property directly: +Det gør faktisk det samme som at tildele det som en egenskab direkte: ```js run class User { } @@ -29,13 +29,13 @@ User.staticMethod = function() { User.staticMethod(); // true ``` -The value of `this` in `User.staticMethod()` call is the class constructor `User` itself (the "object before dot" rule). +Værdien af `this` i et `User.staticMethod()` kald er klassens konstruktør `User` selv ("objektet før punktum" reglen). -Usually, static methods are used to implement functions that belong to the class as a whole, but not to any particular object of it. +Normalt bruges statiske metoder til at implementere funktioner, der tilhører klassen som en helhed, men ikke et bestemt objekt af den. -For instance, we have `Article` objects and need a function to compare them. +For eksempel har vi `Article` objekter og har brug for en funktion til at sammenligne dem. -A natural solution would be to add `Article.compare` static method: +En naturlig løsning ville være at tilføje den statiske metode `Article.compare`, som kan sammenligne to artikler: ```js run class Article { @@ -53,9 +53,9 @@ class Article { // usage let articles = [ - new Article("HTML", new Date(2019, 1, 1)), - new Article("CSS", new Date(2019, 0, 1)), - new Article("JavaScript", new Date(2019, 11, 1)) + new Article("HTML", new Date(2027, 1, 1)), + new Article("CSS", new Date(2027, 0, 1)), + new Article("JavaScript", new Date(2027, 11, 1)) ]; *!* @@ -65,19 +65,19 @@ articles.sort(Article.compare); alert( articles[0].title ); // CSS ``` -Here `Article.compare` method stands "above" articles, as a means to compare them. It's not a method of an article, but rather of the whole class. +Her vil metoden `Article.compare` stå "over" de enkelte artikler, som et middel til at sammenligne dem. Det er ikke en metode for den enkelte artikel, men mere en for hele klassen. -Another example would be a so-called "factory" method. +Et andet eksempel ville være en såkaldt "factory" metode. -Let's say, we need multiple ways to create an article: +Lad os sige, vi har brug for flere måder at oprette en artikel på: -1. Create by given parameters (`title`, `date` etc). -2. Create an empty article with today's date. -3. ...or else somehow. +1. Opret ved hjælp af givne parametre (`title`, `date` etc). +2. Opret en tom artikel med dagens dato. +3. ...eller noget helt tredje. -The first way can be implemented by the constructor. And for the second one we can make a static method of the class. +Den første måde kan implementeres ved hjælp af konstruktøren. Og for den anden måde kan vi lave en statisk metode for klassen. -Such as `Article.createTodays()` here: +Sådan som `Article.createTodays()` her: ```js run class Article { @@ -88,43 +88,43 @@ class Article { *!* static createTodays() { - // remember, this = Article - return new this("Today's digest", new Date()); + // husk, this = Article + return new this("Dagens sammendrag", new Date()); } */!* } let article = Article.createTodays(); -alert( article.title ); // Today's digest +alert( article.title ); // Dagens sammendrag ``` -Now every time we need to create a today's digest, we can call `Article.createTodays()`. Once again, that's not a method of an article, but a method of the whole class. +Nu, hver gang vi vil oprette en dagens sammendrag, kan vi kalde `Article.createTodays()`. Igen, det er ikke en metode for den enkelte artikel, men en metode for hele klassen. -Static methods are also used in database-related classes to search/save/remove entries from the database, like this: +Statiske metoder bruges også i database-relaterede klasser til at søge/gemme/fjerne indlæg fra databasen, som dette: ```js -// assuming Article is a special class for managing articles -// static method to remove the article by id: +// forudsat at Article er en speciel klasse til at håndtere artikler +// statisk metode til at fjerne artiklen ved hjælp af id: Article.remove({id: 12345}); ``` -````warn header="Static methods aren't available for individual objects" -Static methods are callable on classes, not on individual objects. +````warn header="Statiske metoder er ikke tilgængelige for individuelle objekter" +Statiske metoder kan kun kaldes på klasser, ikke på individuelle objekter. -E.g. such code won't work: +F.eks. vil følgende kode ikke virke, fordi `createTodays` er en statisk metode og ikke findes på det enkelte artikelobjekt: ```js // ... -article.createTodays(); /// Error: article.createTodays is not a function +article.createTodays(); /// Fejl: article.createTodays is not a function ``` ```` -## Static properties +## Statiske egenskaber [recent browser=Chrome] -Static properties are also possible, they look like regular class properties, but prepended by `static`: +Statiske egenskaber er også mulige, de ser ud som normale klasseegenskaber, men er præfikseret med `static`: ```js run class Article { @@ -134,21 +134,21 @@ class Article { alert( Article.publisher ); // Ilya Kantor ``` -That is the same as a direct assignment to `Article`: +Dette er det samme som en direkte tildeling til `Article`: ```js Article.publisher = "Ilya Kantor"; ``` -## Inheritance of static properties and methods [#statics-and-inheritance] +## Nedarvning af statiske egenskaber og metoder [#statics-and-inheritance] -Static properties and methods are inherited. +Statiske egenskaber og metoder nedarves. -For instance, `Animal.compare` and `Animal.planet` in the code below are inherited and accessible as `Rabbit.compare` and `Rabbit.planet`: +For eksempel, `Animal.compare` og `Animal.planet` i koden nedenfor nedarves og er tilgængelige som `Rabbit.compare` og `Rabbit.planet`: ```js run class Animal { - static planet = "Earth"; + static planet = "Jorden"; constructor(name, speed) { this.speed = speed; @@ -157,7 +157,7 @@ class Animal { run(speed = 0) { this.speed += speed; - alert(`${this.name} runs with speed ${this.speed}.`); + alert(`${this.name} løber ${this.speed} km/t.`); } *!* @@ -168,64 +168,64 @@ class Animal { } -// Inherit from Animal +// Nedarver fra Animal class Rabbit extends Animal { hide() { - alert(`${this.name} hides!`); + alert(`${this.name} skjuler sig!`); } } let rabbits = [ - new Rabbit("White Rabbit", 10), - new Rabbit("Black Rabbit", 5) + new Rabbit("Hvid kanin", 10), + new Rabbit("Sort kanin", 5) ]; *!* rabbits.sort(Rabbit.compare); */!* -rabbits[0].run(); // Black Rabbit runs with speed 5. +rabbits[0].run(); // Sort kanin løber 5 km/t. -alert(Rabbit.planet); // Earth +alert(Rabbit.planet); // Jorden ``` -Now when we call `Rabbit.compare`, the inherited `Animal.compare` will be called. +Nu, når vi kalder `Rabbit.compare` vil `Animal.compare` blive kaldt. -How does it work? Again, using prototypes. As you might have already guessed, `extends` gives `Rabbit` the `[[Prototype]]` reference to `Animal`. +Hvordan virker det? Igen, ved hjælp af prototyper. Som du nok har gættet så vil `extends` pege `Rabbit` referencen `[[Prototype]]` til `Animal`. ![](animal-rabbit-static.svg) -So, `Rabbit extends Animal` creates two `[[Prototype]]` references: +Så, `Rabbit extends Animal` opretter to `[[Prototype]]` referencer: -1. `Rabbit` function prototypally inherits from `Animal` function. -2. `Rabbit.prototype` prototypally inherits from `Animal.prototype`. +1. `Rabbit` funktioner nedarver via prototype fra `Animal` funktioner. +2. `Rabbit.prototype` nedarver via prototype fra `Animal.prototype`. -As a result, inheritance works both for regular and static methods. +Som resultat virker nedarvning både for normale og statiske metoder. -Here, let's check that by code: +Lad os tjekke det med kode: ```js run class Animal {} class Rabbit extends Animal {} -// for statics +// for statiske metoder alert(Rabbit.__proto__ === Animal); // true -// for regular methods +// for regulære metoder alert(Rabbit.prototype.__proto__ === Animal.prototype); // true ``` -## Summary +## Opsummering -Static methods are used for the functionality that belongs to the class "as a whole". It doesn't relate to a concrete class instance. +Statiske metoder bruges til funktionalit, der hører til klassen "som en helhed". Det relaterer sig ikke til en konkrete klasseinstans. -For example, a method for comparison `Article.compare(article1, article2)` or a factory method `Article.createTodays()`. +For eksempel, en metode til sammenligning `Article.compare(article1, article2)` eller en factory-metode `Article.createTodays()`. -They are labeled by the word `static` in class declaration. +De er mærket med ordet `static` i klassedeklarationen. -Static properties are used when we'd like to store class-level data, also not bound to an instance. +Statiske egenskaber bruges, når vi vil gemme data på klasseniveau, som ikke er bundet til en instans. -The syntax is: +Syntaksen er den samme for både statiske metoder og egenskaber: ```js class MyClass { @@ -237,13 +237,13 @@ class MyClass { } ``` -Technically, static declaration is the same as assigning to the class itself: +Teknisk set er en statisk deklaration det samme som at tildele til selve klassen: ```js MyClass.property = ... MyClass.method = ... ``` -Static properties and methods are inherited. +Statiske egenskaber og metoder nedarves. -For `class B extends A` the prototype of the class `B` itself points to `A`: `B.[[Prototype]] = A`. So if a field is not found in `B`, the search continues in `A`. +For `class B extends A` vil prototypen af klassen `B` selv pege på `A`: `B.[[Prototype]] = A`. Så hvis et felt ikke findes i `B`, søges der videre i `A`.