diff --git a/concepts/closures/introduction.md b/concepts/closures/introduction.md index c5104af10d..d443933587 100644 --- a/concepts/closures/introduction.md +++ b/concepts/closures/introduction.md @@ -1,6 +1,7 @@ # Introduction -**Closures** are a programming pattern in JavaScript that allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. JavaScript supports closures transparently, and they are often used without knowing what they are. +**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. +JavaScript supports closures transparently, and they are often used without knowing what they are. ```javascript // Top-level declarations are global-scope @@ -12,16 +13,38 @@ const dozen = 12; const twoDozen = dozen * 2; } +// Because of the block-scope declaration, twoDozen is not available here. +twoDozen; +// => Uncaught ReferenceError: twoDozen is not defined +``` + +Except for braces `{}`, functions (and classes) als create new scopes, which can _enclose_ values: + +```javascript +const dozen = 12; + // Functions create a new function-scope and block-scope. // Referencing the outer variable here is a closure. function nDozen(n) { - return dozen * n; + // This is declared inside the function scope, and uses the top-level scope. + // This works, and encloses the value 12. + const twoDozen = dozen * 2; + + // This only uses the locally declared variable and the passed argument to the parameter `n` + return (twoDozen / 2) * n; } + +// Because of the function-scope declaration, twoDozen is not available here. +twoDozen; +// => Uncaught ReferenceError: twoDozen is not defined ``` +As the `twoDozen` examples show, values can be enclosed in a _nested_ scope (function, block, etc.), but cannot be pulled out of that context. +In the majority of cases, it is intended in Modern JavaScript that a value does not _leak_ to an outside scope. + ## Closures to save state and pass along values -Using a mutable variable declaration (like `let` or `var`) allows for state to be preserved: +Using a mutable variable declaration (like `let` or `var`) allows for some state to be preserved: ```javascript let counter = 0; @@ -32,6 +55,67 @@ export function increment() { counter += 1; return counter; } + +increment(); +// => 1 + +counter; +// => 1 +``` + +## Enclosing values without leaking the state + +Combining the two ideas: enclosing a value to preserve state, and enclosed values do not leak to the outside, it's possible to create private values. + +The most common method is to make a function that returns a function which encloses some state. + +```javascript +export function makeCounter() { + let counter = 0; + + // This returns a new function that encloses the local variable counter + return function increment() { + counter += 1; + return counter; + }; +} + +// Counter did not leak +counter; +// => Uncaught ReferenceError: counter is not defined + +// This creates a new counter. +// This assigns the increment function to the variable myFirstCounter. +const myFirstCounter = makeCounter(); + +typeof myFirstCounter; +// => function + +myFirstCounter.name; +// => increment + +myFirstCounter(); +// => 1 +myFirstCounter(); +// => 2 + +// This creates new counter (with new, separate local state / enclosed counter variable) +const mySecondCounter = makeCounter(); + +mySecondCounter(); +// => 1 + +// It is not affect the first counter. + +myFirstCounter(); +// => 3 +``` + +```exercism/note +Many programmers find closures a hard concept, and returning a function from a function is not common or not even possible in all programming languages. +If you want more reading material, the [guide on MDN on Closures][mdn-closures] is quite comprehensive. + +[mdn-closures]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures ``` [wiki-lexical-scope]: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping diff --git a/exercises/concept/bird-watcher/.docs/instructions.md b/exercises/concept/bird-watcher/.docs/instructions.md index f08c9f735e..5ff31058bd 100644 --- a/exercises/concept/bird-watcher/.docs/instructions.md +++ b/exercises/concept/bird-watcher/.docs/instructions.md @@ -13,9 +13,11 @@ To practice, use a `for` loop to solve each of the tasks below. ## 1. Determine the total number of birds that you counted so far -Let us start analyzing the data by getting a high-level view. Find out how many birds you counted in total since you started your logs. +Let us start analyzing the data by getting a high-level view. +Find out how many birds you counted in total since you started your logs. -Implement a function `totalBirdCount` that accepts an array that contains the bird count per day. It should return the total number of birds that you counted. +Implement a function `totalBirdCount` that accepts an array that contains the bird count per day. +It should return the total number of birds that you counted. ```javascript birdsPerDay = [2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1]; @@ -28,7 +30,8 @@ totalBirdCount(birdsPerDay); Now that you got a general feel for your bird count numbers, you want to make a more fine-grained analysis. Implement a function `birdsInWeek` that accepts an array of bird counts per day and a week number. -It returns the total number of birds that you counted in that specific week. You can assume weeks are always tracked completely. +It returns the total number of birds that you counted in that specific week. +You can assume weeks are always tracked completely. ```javascript birdsPerDay = [2, 5, 0, 7, 4, 1, 3, 0, 2, 5, 0, 1, 3, 1]; diff --git a/exercises/concept/coordinate-transformation/.docs/introduction.md b/exercises/concept/coordinate-transformation/.docs/introduction.md index 7af38ff52e..d443933587 100644 --- a/exercises/concept/coordinate-transformation/.docs/introduction.md +++ b/exercises/concept/coordinate-transformation/.docs/introduction.md @@ -1,6 +1,7 @@ # Introduction -**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. JavaScript supports closures transparently, and they are often used without knowing what they are. +**Closures** are a programming pattern in JavaScript which allows variables from an outer [lexical scope][wiki-lexical-scope] to be used inside of a nested block of code. +JavaScript supports closures transparently, and they are often used without knowing what they are. ```javascript // Top-level declarations are global-scope @@ -12,13 +13,35 @@ const dozen = 12; const twoDozen = dozen * 2; } +// Because of the block-scope declaration, twoDozen is not available here. +twoDozen; +// => Uncaught ReferenceError: twoDozen is not defined +``` + +Except for braces `{}`, functions (and classes) als create new scopes, which can _enclose_ values: + +```javascript +const dozen = 12; + // Functions create a new function-scope and block-scope. // Referencing the outer variable here is a closure. function nDozen(n) { - return dozen * n; + // This is declared inside the function scope, and uses the top-level scope. + // This works, and encloses the value 12. + const twoDozen = dozen * 2; + + // This only uses the locally declared variable and the passed argument to the parameter `n` + return (twoDozen / 2) * n; } + +// Because of the function-scope declaration, twoDozen is not available here. +twoDozen; +// => Uncaught ReferenceError: twoDozen is not defined ``` +As the `twoDozen` examples show, values can be enclosed in a _nested_ scope (function, block, etc.), but cannot be pulled out of that context. +In the majority of cases, it is intended in Modern JavaScript that a value does not _leak_ to an outside scope. + ## Closures to save state and pass along values Using a mutable variable declaration (like `let` or `var`) allows for some state to be preserved: @@ -32,6 +55,67 @@ export function increment() { counter += 1; return counter; } + +increment(); +// => 1 + +counter; +// => 1 +``` + +## Enclosing values without leaking the state + +Combining the two ideas: enclosing a value to preserve state, and enclosed values do not leak to the outside, it's possible to create private values. + +The most common method is to make a function that returns a function which encloses some state. + +```javascript +export function makeCounter() { + let counter = 0; + + // This returns a new function that encloses the local variable counter + return function increment() { + counter += 1; + return counter; + }; +} + +// Counter did not leak +counter; +// => Uncaught ReferenceError: counter is not defined + +// This creates a new counter. +// This assigns the increment function to the variable myFirstCounter. +const myFirstCounter = makeCounter(); + +typeof myFirstCounter; +// => function + +myFirstCounter.name; +// => increment + +myFirstCounter(); +// => 1 +myFirstCounter(); +// => 2 + +// This creates new counter (with new, separate local state / enclosed counter variable) +const mySecondCounter = makeCounter(); + +mySecondCounter(); +// => 1 + +// It is not affect the first counter. + +myFirstCounter(); +// => 3 +``` + +```exercism/note +Many programmers find closures a hard concept, and returning a function from a function is not common or not even possible in all programming languages. +If you want more reading material, the [guide on MDN on Closures][mdn-closures] is quite comprehensive. + +[mdn-closures]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures ``` [wiki-lexical-scope]: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping diff --git a/exercises/concept/custom-signs/.docs/instructions.md b/exercises/concept/custom-signs/.docs/instructions.md index 12b8ddd326..3a8a659d6f 100644 --- a/exercises/concept/custom-signs/.docs/instructions.md +++ b/exercises/concept/custom-signs/.docs/instructions.md @@ -4,7 +4,8 @@ In this exercise you'll be writing code to help a sign company create custom mes ## 1. Build an occasion sign -Implement the function `buildSign(occasion, name)` that accepts a string as the `occasion` parameter and a string holding someone's name as the `name` parameter. The two parameters will be embedded into a template string to output the message on the sign. +Implement the function `buildSign(occasion, name)` that accepts a string as the `occasion` parameter and a string holding someone's name as the `name` parameter. +The two parameters will be embedded into a template string to output the message on the sign. ```javascript buildSign('Birthday', 'Rob'); @@ -13,7 +14,9 @@ buildSign('Birthday', 'Rob'); ## 2. Build a birthday sign -Implement the function `buildBirthdaySign(age)` that accepts an age and based on the age will determine part of the message on the sign. If the age is 50 or older, the sign will refer user as _mature_, else it will refer them as _young_. The exact expected output is shown below: +Implement the function `buildBirthdaySign(age)` that accepts an age and based on the age will determine part of the message on the sign. +If the age is 50 or older, the sign will refer user as _mature_, else it will refer them as _young_. +The exact expected output is shown below: ```javascript buildBirthdaySign(50); diff --git a/exercises/concept/elyses-analytic-enchantments/.docs/introduction.md b/exercises/concept/elyses-analytic-enchantments/.docs/introduction.md index c90f47182d..489b79e710 100644 --- a/exercises/concept/elyses-analytic-enchantments/.docs/introduction.md +++ b/exercises/concept/elyses-analytic-enchantments/.docs/introduction.md @@ -63,11 +63,13 @@ numbers.indexOf('two'); // => 1 ``` -Some other helpful built-in methods that are available to analyze an array are shown below. See [MDN][mdn-array-methods] for a full list of array methods. +Some other helpful built-in methods that are available to analyze an array are shown below. +See [MDN][mdn-array-methods] for a full list of array methods. ### `includes` -> The includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate. [^1] +The `includes(value)` method determines whether an array includes a certain value. +It returns `true` when the value is included, `false` otherwise. ```javascript const numbers = [1, 'two', 3, 'four']; @@ -79,7 +81,10 @@ numbers.includes('one'); ### `every` -> The every() method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value. [^2] +The `every(predicate)` method take a function which is _a predicate_. +It tests whether all elements in the array return `true` when passed to the predicate. +In other words: the methods tests that all its elements pass the test passed to the function call. +It returns `true` when every element passes the predicate test, `false` otherwise. ```javascript const numbers = [1, 3, 5, 7, 9]; @@ -89,7 +94,7 @@ numbers.every((num) => num % 2 !== 0); ### `some` -> The some() method tests whether at least one element in the array passes the test implemented by the provided function. [^3] +The `some(predicate)` method is the same as the `every` method, but returns `true` if at least one item in the array passes the _predicate_ test. ```javascript const numbers = [1, 3, 5, 7, 9]; @@ -99,7 +104,9 @@ numbers.some((num) => num % 2 !== 0); ### `find` -> The find() method returns the value of the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned. [^4] +The `find(predicate)` method returns the value of the first element in the array that passes the `predicate` test. +Where `some()` returns `true` when it passes, `find()` returns the actual value in the array. +The method returns `undefined` when none of the elements in the array pass the _predicate_ test. ```javascript const numbers = [1, 3, 5, 7, 9]; @@ -109,7 +116,8 @@ numbers.find((num) => num < 5); ### `findIndex` -> The findIndex() method returns the index of the first element in the array that satisfies the provided testing function. Otherwise, it returns -1, indicating that no element passed the test. [^5] +The `findIndex(predicate)` is the same as the `find()` method, but it returns the (first) _index_ of the element that passes the _predicate_ test instead of the `value`. +The method returns `-1` when none of the elements in the array pass the _predicate_ test. ```javascript const numbers = [1, 3, 5, 7, 9]; @@ -119,16 +127,6 @@ numbers.findIndex((num) => num > 9); // => -1 ``` -[^1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes - -[^2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every - -[^3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some - -[^4]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find - -[^5]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex - [predicate_in_programming]: https://derk-jan.com/2020/05/predicate/ [mdn-array-methods]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods [arrays-concept]: /tracks/javascript/concepts/arrays diff --git a/exercises/concept/elyses-enchantments/.docs/instructions.md b/exercises/concept/elyses-enchantments/.docs/instructions.md index 3889a59887..8298853c08 100644 --- a/exercises/concept/elyses-enchantments/.docs/instructions.md +++ b/exercises/concept/elyses-enchantments/.docs/instructions.md @@ -11,7 +11,9 @@ etc. ~~~~exercism/note -All functions should update the array of cards and then return the modified array - a common way of working known as the Builder pattern, which allows you to nicely daisy-chain functions together. +All but two functions should update the array of cards and then return the modified array - a common way of working known as the Builder pattern, which allows you to nicely daisy-chain functions together. + +The two exceptions are `getItem`, which should return the card at the given position, and `checkSizeOfStack` which should return `true` if the given size matches. ~~~~ diff --git a/exercises/concept/elyses-enchantments/.docs/introduction.md b/exercises/concept/elyses-enchantments/.docs/introduction.md index 5cc2203486..6f9c6a144f 100644 --- a/exercises/concept/elyses-enchantments/.docs/introduction.md +++ b/exercises/concept/elyses-enchantments/.docs/introduction.md @@ -33,12 +33,13 @@ numbers; ## Methods -Some of the [methods][array_methods] that are available on every Array object can be used to add or remove from the array. +Some of the [methods][mdn-array] that are available on every Array object can be used to add or remove from the array. Here are a few to consider when working on this exercise: ### push -> The `push()` method adds one or more elements to the end of an array and returns the new length of the array.[^1] +A `value` can be _added_ to the end of an array by using `.push(value)`. +The method returns the new length of the array. ```javascript const numbers = [1, 'two', 3, 'four']; @@ -49,8 +50,9 @@ numbers; ### pop -> The `pop()` method removes the last element from an array and returns that element. -> This method changes the length of the array.[^2] +The _last_ `value` can be _removed_ from an array by using `.pop()` +The method returns the removed value. +The length of the array will be decreased because of this change. ```javascript const numbers = [1, 'two', 3, 'four']; @@ -61,8 +63,9 @@ numbers; ### shift -> The `shift()` method removes the first element from an array and returns that removed element. -> This method changes the length of the array.[^3] +The _first_ `value` can be _removed_ from an array by using `.shift()` +The method returns the removed value. +The length of the array will be decreased because of this change. ```javascript const numbers = [1, 'two', 3, 'four']; @@ -73,7 +76,8 @@ numbers; ### unshift -> The unshift() method adds one or more elements to the beginning of an array and returns the new length of the array.[^4] +A `value` can be _added_ to the beginning of an array by using `.unshift(value)`. +The method returns the new length of the array. ```javascript const numbers = [1, 'two', 3, 'four']; @@ -84,8 +88,8 @@ numbers; ### splice -> The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place. -> This method returns an array containing the deleted elements.[^5] +A `value` at a specific `index` can be _removed_ from an array by using `.splice(index, 1)`. +The method returns the removed element(s). ```javascript const numbers = [1, 'two', 3, 'four']; @@ -94,16 +98,17 @@ numbers; // => [1, 'two', 'one', 'four'] ``` ---- + +~~~exercism/advanced +These methods are more powerful than described: -[^1]: `push`, MDN. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push (referenced September 29, 2021) +- Both `push` and `unshift` allow you to push or unshift multiple values at once, by adding more arguments. + That is not necessary to complete this exercise. +- Splice can remove multiple values by increasing the second argument. + That is not necessary to complete this exercise. +- Splice can also add multiple values by adding them as arguments after the `deleteCount`. + This can be used to replace values, or insert values in the middle of an array (for example by removing 0 elements). + That is not necessary to complete this exercise. +~~~ -[^2]: `pop`, MDN. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop (referenced September 29, 2021) - -[^3]: `shift`, MDN. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift (referenced September 29, 2021) - -[^4]: `unshift`, MDN. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift (referenced September 29, 2021) - -[^5]: `splice`, MDN. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice (referenced September 29, 2021) - -[array_methods]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array +[mdn-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array diff --git a/exercises/concept/factory-sensors/.docs/instructions.md b/exercises/concept/factory-sensors/.docs/instructions.md index b8c47f3f9b..545c242b4e 100644 --- a/exercises/concept/factory-sensors/.docs/instructions.md +++ b/exercises/concept/factory-sensors/.docs/instructions.md @@ -1,6 +1,8 @@ # Instructions -Elena is the new quality manager of a newspaper factory. As she has just arrived in the company, she has decided to review some of the processes in the factory to see what could be improved. She found out that technicians are doing a lot of quality checks by hand. She sees there is a good opportunity for automation and asks you, a freelance developer, to develop a piece of software to monitor some of the machines. +Elena is the new quality manager of a newspaper factory. As she has just arrived in the company, she has decided to review some of the processes in the factory to see what could be improved. +She found out that technicians are doing a lot of quality checks by hand. +She sees there is a good opportunity for automation and asks you, a freelance developer, to develop a piece of software to monitor some of the machines. ## 1. Monitor the humidity level of the room @@ -63,20 +65,26 @@ Implements a function `monitorTheMachine` that takes an argument `actions`. `actions` is an object that has 4 properties : -- `check` is a _*function*_ that, when called, checks the temperature of the machine. - It may throw various errors - -- `alertDeadSensor` is a _*function*_ that, when called, alerts a technician that the temperature's sensor is dead. - -- `alertOverheating` is a _*function*_ that, when called, will turn on a warning light on the machine. - -- `shutdown` is a _*function*_ that, when called, will turn off the machine. - -The `monitorTheMachine` function should call `check()`. If it passes, the function should not return anything. However, it may `throw` an error. When this happens, you should, depending on the error: - -- `ArgumentError`: when this happens, call the `alertDeadSensor` function. -- `OverheatingError`: when this happens, if the temperature is less than 600 °C, call the `alertOverheating` function to turn on the warning light. If the temperature exceeds 600°C, the situation is critical, call the `shutdown` function. -- _anything else_: when this happens, rethrow the error +| property | description | +| ------------------ | ----------------------------------------------------------------------------------- | +| `check` | a _*function*_. Checks the temperature of the machine. It may throw various errors. | +| `alertDeadSensor` | a _*function*_. Alerts a technician that the temperature's sensor is dead. | +| `alertOverheating` | a _*function*_. Will turn on a warning light on the machine. | +| `shutdown` | a _*function*_. Will turn off the machine. | + +The `monitorTheMachine(actions)` function should internally call `check()`. +If that passes, the function should not return anything. +If that `throw`s an error, different behaviour is expected: + +| exception | expected behaviour | +| ------------------ | ------------------------------------ | +| `ArgumentError` | call the `alertDeadSensor` function. | +| `OverheatingError` | execute the overheating protocol. | +| _(anything else)_ | rethrow the error | + +**Overheating protocol** +If the temperature is less than 600 °C, turn on the warning light by calling the `alertOverheating` function. +If the temperature exceeds 600 °C, the situation is critical, so call the `shutdown` function. ```javascript monitorTheMachine({ diff --git a/exercises/concept/freelancer-rates/.docs/instructions.md b/exercises/concept/freelancer-rates/.docs/instructions.md index d802bfdcb8..85649c1e77 100644 --- a/exercises/concept/freelancer-rates/.docs/instructions.md +++ b/exercises/concept/freelancer-rates/.docs/instructions.md @@ -1,6 +1,7 @@ # Instructions -In this exercise you will be writing code to help a freelancer communicate with their clients about the prices of certain projects. You will write a few utility functions to quickly calculate the costs for the clients. +In this exercise you will be writing code to help a freelancer communicate with their clients about the prices of certain projects. +You will write a few utility functions to quickly calculate the costs for the clients. ```exercism/note The `ratePerHour` variable and the `dayRate` function are related to money. diff --git a/exercises/concept/freelancer-rates/.docs/introduction.md b/exercises/concept/freelancer-rates/.docs/introduction.md index 3e2edcaedd..f68386e39a 100644 --- a/exercises/concept/freelancer-rates/.docs/introduction.md +++ b/exercises/concept/freelancer-rates/.docs/introduction.md @@ -14,7 +14,8 @@ Otherwise, the `number` type is likely the better option. ### Rounding -There is a built-in global object called `Math` that provides various [rounding functions][ref-math-object-rounding]. For example, you can round down (`floor`) or round up (`ceil`) decimal numbers to the nearest whole numbers. +There is a built-in global object called `Math` that provides various [rounding functions][ref-math-object-rounding]. +For example, you can round down (`floor`) or round up (`ceil`) decimal numbers to the nearest whole numbers. ```javascript Math.floor(234.34); // => 234 diff --git a/exercises/concept/fruit-picker/.docs/instructions.md b/exercises/concept/fruit-picker/.docs/instructions.md index aecdeb09ca..278dd8c47f 100644 --- a/exercises/concept/fruit-picker/.docs/instructions.md +++ b/exercises/concept/fruit-picker/.docs/instructions.md @@ -1,10 +1,14 @@ # Instructions -You are creating a new online portal for your patrons to order their fruit fresh from the grocer. The grocer has an API that you can use to see if they have the inventory desired by your customers. You need to create a small library of functions for interacting with the grocer's API. +You are creating a new online portal for your patrons to order their fruit fresh from the grocer. +The grocer has an API that you can use to see if they have the inventory desired by your customers. +You need to create a small library of functions for interacting with the grocer's API. ## 1. Notify your customer when their order was successful -The portal should notify your customer if their order was successful. Define the `onSuccess` callback function that will be called if the order was successful due to the grocer having enough fruit in stock. This function should invoke the imported `notify` function, passing `{ message: 'SUCCESS' }` to let your customer know that their order was successful. +The portal should notify your customer if their order was successful. +Define the `onSuccess` callback function that will be called if the order was successful due to the grocer having enough fruit in stock. +This function should invoke the imported `notify` function, passing `{ message: 'SUCCESS' }` to let your customer know that their order was successful. ```javascript onSuccess(); @@ -13,7 +17,9 @@ onSuccess(); ## 2. Notify your customer when their order was unsuccessful -The portal should notify your customer if their order was unsuccessful. Define the `onError` callback function that will be called if the order was unsuccessful because the grocer _does not have_ the fruit in stock or there was an error. This function should invoke the imported `notify` function, passing `{ message: 'ERROR' }` to let your customer know that their order was unsuccessful. +The portal should notify your customer if their order was unsuccessful. +Define the `onError` callback function that will be called if the order was unsuccessful because the grocer _does not have_ the fruit in stock or there was an error. +This function should invoke the imported `notify` function, passing `{ message: 'ERROR' }` to let your customer know that their order was unsuccessful. ```javascript onError(); @@ -22,9 +28,11 @@ onError(); ## 3. Create an API wrapper to wrap the grocer's API order function -Fruit orders are placed through the grocer's API via the provided `order` function. This function receives three arguments: a _query_, containing the `variety` and `quantity` of fruit requested, a _callback_ function to be invoked when the order is successful, and a _callback_ function to be invoked when the order encounters an error. +Fruit orders are placed through the grocer's API via the provided `order` function. +This function receives three arguments: a _query_, containing the `variety` and `quantity` of fruit requested, a _callback_ function to be invoked when the order is successful, and a _callback_ function to be invoked when the order encounters an error. -You want to insulate your codebase from potential external changes and decide to wrap the call to the `order` function inside a new function named `orderFromGrocer`. Implement the `orderFromGrocer` function that attempts to place an order via a call to the grocer's API `order` function, making sure to forward the arguments passed into `orderFromGrocer` to the API call. +You want to insulate your codebase from potential external changes and decide to wrap the call to the `order` function inside a new function named `orderFromGrocer`. +Implement the `orderFromGrocer` function that attempts to place an order via a call to the grocer's API `order` function, making sure to forward the arguments passed into `orderFromGrocer` to the API call. The query takes the form of an _object_: @@ -46,7 +54,9 @@ orderFromGrocer( ## 4. Simplify handling placed orders -Your customers are now able to place fruit orders via your portal, however, you notice that you are invoking the `orderFromGrocer` function in many different places across your codebase, each time having to pass in a `query` and the two `callback` functions as arguments. Seeing an opportunity to refactor your code, you think it would be simpler if you could place an order by just passing the `variety` and `quantity` of fruit required. Define the `postOrder` helper function that takes `variety` and `quantity` as arguments and attempts to place an order with the grocer. +Your customers are now able to place fruit orders via your portal, however, you notice that you are invoking the `orderFromGrocer` function in many different places across your codebase, each time having to pass in a `query` and the two `callback` functions as arguments. +Seeing an opportunity to refactor your code, you think it would be simpler if you could place an order by just passing the `variety` and `quantity` of fruit required. +Define the `postOrder` helper function that takes `variety` and `quantity` as arguments and attempts to place an order with the grocer. ```javascript postOrder('peach', 100); diff --git a/exercises/concept/fruit-picker/.docs/introduction.md b/exercises/concept/fruit-picker/.docs/introduction.md index 3a88419e35..4daee344f1 100644 --- a/exercises/concept/fruit-picker/.docs/introduction.md +++ b/exercises/concept/fruit-picker/.docs/introduction.md @@ -2,7 +2,9 @@ ## Callback functions -Callback functions are functions passed as arguments. This programming pattern creates a sequence of function calls in both synchronous and asynchronous programming. Writing a callback function is no different from writing a function; however, the callback function must match the signature defined by the calling function. +Callback functions are functions passed as arguments. +This programming pattern creates a sequence of function calls in both synchronous and asynchronous programming. +Writing a callback function is no different from writing a function; however, the callback function must match the signature defined by the calling function. ```javascript const squareLength = 5; @@ -20,10 +22,18 @@ function areaOfSquare(number) { applyToSquare(areaOfSquare); // => 25 ``` -You may also write callbacks as a function expression: +You may also write callbacks as a function expression, anonymous function expression, or arrow function expression: ```javascript applyToSquare(function squarePerimeter(side) { return side * 4; }); + +applyToSquare(function (side) { + return side * 4; +}); + +applyToSquare((side) => { + return side * 4; +}); ``` diff --git a/exercises/concept/high-score-board/.docs/introduction.md b/exercises/concept/high-score-board/.docs/introduction.md index 3a28670588..299ca6a78e 100644 --- a/exercises/concept/high-score-board/.docs/introduction.md +++ b/exercises/concept/high-score-board/.docs/introduction.md @@ -7,12 +7,13 @@ Objects are collections of key-value pairs. As such, they can be used in the same way as what are often referred to as maps or dictionaries in other languages. In other languages, all values in a map often need to have the same data type. -In JavaScript, only the type of the key is restricted: it has to be a string. +In JavaScript, only the type of the key is restricted: it has to be a `string`. The values inside one object can have different types. They can be primitive types like numbers but also arrays, other objects or even functions. This makes objects very versatile so that they are also key entities for [object-oriented programming][oop] (OOP) in JavaScript. -In the following, we will focus on objects as collections or maps. Other use cases of objects will be covered in other concepts, see e.g., [Classes][concept-classes]. +In the following, we will focus on objects as collections or maps. +Other use cases of objects will be covered in other concepts, see e.g., [Classes][concept-classes]. ## Creating an Object diff --git a/exercises/concept/lasagna/.docs/introduction.md b/exercises/concept/lasagna/.docs/introduction.md index 2d9cbf3492..f852f68f5c 100644 --- a/exercises/concept/lasagna/.docs/introduction.md +++ b/exercises/concept/lasagna/.docs/introduction.md @@ -2,13 +2,18 @@ JavaScript is a dynamic language, supporting object-oriented, imperative, and declarative (e.g. functional programming) styles. -## (Re-)Assignment +## Variables -There are a few primary ways to assign values to names in JavaScript - using variables or constants. On Exercism, variables are always written in [camelCase][wiki-camel-case]; constants are written in [SCREAMING_SNAKE_CASE][wiki-snake-case]. There is no official guide to follow, and various companies and organizations have various style guides. _Feel free to write variables any way you like_. The upside from writing them the way the exercises are prepared is that they'll be highlighted differently in the web interface and most IDEs. +There are a few primary ways to assign values to names in JavaScript - using variables or constants. +On Exercism, variables are always written in [camelCase][wiki-camel-case]; constants are written in [SCREAMING_SNAKE_CASE][wiki-snake-case]. +There is no official guide to follow, and various companies and organizations have various style guides. +_Feel free to write variables any way you like_. +The upside from writing them the way the exercises are prepared is that they'll be highlighted differently in the web interface and most IDEs. Variables in JavaScript can be defined using the [`const`][mdn-const], [`let`][mdn-let] or [`var`][mdn-var] keyword. -A variable can reference different values over its lifetime when using `let` or `var`. For example, `myFirstVariable` can be defined and redefined many times using the assignment operator `=`: +A variable can reference different values over its lifetime when using `let` or `var`. +For example, `myFirstVariable` can be defined and redefined many times using the assignment operator `=`: ```javascript let myFirstVariable = 1; @@ -16,7 +21,8 @@ myFirstVariable = 'Some string'; myFirstVariable = new SomeComplexClass(); ``` -In contrast to `let` and `var`, variables that are defined with `const` can only be assigned once. This is used to define constants in JavaScript. +In contrast to `let` and `var`, variables that are defined with `const` can only be assigned once. +This is used to define constants in JavaScript. ```javascript const MY_FIRST_CONSTANT = 10; @@ -26,11 +32,16 @@ MY_FIRST_CONSTANT = 20; // => TypeError: Assignment to constant variable. ``` -> 💡 In a later Concept Exercise the difference between _constant_ assignment / binding and _constant_ value is explored and explained. + +~~~exercism/note +💡 In a later Concept Exercise the difference between _constant_ assignment, _constant_ binding, and _constant_ value is explored and explained. +~~~ ## Function Declarations -In JavaScript, units of functionality are encapsulated in _functions_, usually grouping functions together in the same file if they belong together. These functions can take parameters (arguments), and can _return_ a value using the `return` keyword. Functions are invoked using `()` syntax. +In JavaScript, units of functionality are encapsulated in _functions_, usually grouping functions together in the same file if they belong together. +These functions have parameters (so they can take arguments), and can _return_ a value using the `return` keyword. +Functions are invoked using `()` syntax. ```javascript function add(num1, num2) { @@ -41,11 +52,31 @@ add(1, 3); // => 4 ``` -> 💡 In JavaScript there are _many_ different ways to declare a function. These other ways look different than using the `function` keyword. The track tries to gradually introduce them, but if you already know about them, feel free to use any of them. In most cases, using one or the other isn't better or worse. +In this example, the function name is `add`. +It has two parameters, `num1` and `num2`. +It returns a value: the result of the expression `num1 + num2` + +Then the function `add` is _called_ using two arguments: `1` and `3`. +The result of the function, the returned value, is `4`. + +```exercism/note +💡 In JavaScript there are _many_ different ways to declare a function. +Some of these other ways look different than using the `function` keyword. +The track tries to gradually introduce them, but if you already know about them, feel free to use any of them. +In most cases, using one or the other isn't better or worse. +``` ## Exposing to Other Files -To make a `function`, a constant, or a variable available in _other files_, they need to be [exported][mdn-export] using the `export` keyword. Another file may then [import][mdn-import] these using the `import` keyword. This is also known as the module system. A great example is how all the tests work. Each exercise has at least one file, for example `lasagna.js`, which contains the _implementation_. Additionally there is at least one other file, for example `lasagna.spec.js`, that contains the _tests_. This file _imports_ the public (i.e. exported) entities in order to test the implementation: +To make a `function`, a constant, or a variable available in _other files_, they need to be [exported][mdn-export] using the `export` keyword. +Another file may then [import][mdn-import] these using the `import` keyword. +This is also known as the module system. + +A great example is how all the tests work. +Each exercise has at least one file, for example `lasagna.js`, which contains the _implementation_. +The _implementation_ is `export`ed from the file, making it available to import in another file. +Additionally there is at least one other file, for example `lasagna.spec.js`, that contains the _tests_. +This file `import`s the public (i.e. `export`ed) entities in order to test the implementation: ```javascript // file.js diff --git a/exercises/concept/poetry-club-door-policy/.meta/exemplar.js b/exercises/concept/poetry-club-door-policy/.meta/exemplar.js index 65d2d57941..7aaca7cf1c 100644 --- a/exercises/concept/poetry-club-door-policy/.meta/exemplar.js +++ b/exercises/concept/poetry-club-door-policy/.meta/exemplar.js @@ -30,8 +30,7 @@ export function frontDoorPassword(word) { * @returns {string} */ export function backDoorResponse(line) { - const trimmed = line.trim(); - return trimmed[trimmed.length - 1]; + return line.trimEnd().slice(-1); } /**