make sure a solution always shows up, use "demo" if exists

This commit is contained in:
Ilya Kantor 2019-02-21 19:35:04 +03:00
parent 360be9ed99
commit 408ba7d4e4
25 changed files with 59 additions and 95 deletions

View file

@ -1,10 +1 @@
Just loop over the object and `return false` immediately if there's at least one property. Just loop over the object and `return false` immediately if there's at least one property.
```js
function isEmpty(obj) {
for (let key in obj) {
return false;
}
return true;
}
```

View file

@ -1,19 +0,0 @@
``` js run
// before the call
let menu = {
width: 200,
height: 300,
title: "My menu"
};
function multiplyNumeric(obj) {
for (let key in obj) {
if (typeof obj[key] == 'number') {
obj[key] *= 2;
}
}
}
alert(menu);
```

View file

@ -1,6 +1,5 @@
```js run demo solution
```js run demo
let calculator = { let calculator = {
sum() { sum() {
return this.a + this.b; return this.a + this.b;
@ -20,4 +19,3 @@ calculator.read();
alert( calculator.sum() ); alert( calculator.sum() );
alert( calculator.mul() ); alert( calculator.mul() );
``` ```

View file

@ -1,6 +1,6 @@
The solution is to return the object itself from every call. The solution is to return the object itself from every call.
```js run ```js run demo
let ladder = { let ladder = {
step: 0, step: 0,
up() { up() {
@ -37,4 +37,3 @@ ladder
.down() .down()
.showStep(); // 1 .showStep(); // 1
``` ```

View file

@ -1,5 +1,3 @@
```js run demo ```js run demo
function Calculator() { function Calculator() {

View file

@ -2,10 +2,9 @@ The maximal length must be `maxlength`, so we need to cut it a little shorter, t
Note that there is actually a single unicode character for an ellipsis. That's not three dots. Note that there is actually a single unicode character for an ellipsis. That's not three dots.
```js run ```js run demo
function truncate(str, maxlength) { function truncate(str, maxlength) {
return (str.length > maxlength) ? return (str.length > maxlength) ?
str.slice(0, maxlength - 1) + '…' : str; str.slice(0, maxlength - 1) + '…' : str;
} }
``` ```

View file

@ -1,5 +0,0 @@
```js run
function extractCurrencyValue(str) {
return +str.slice(1);
}
```

View file

@ -1,4 +1,4 @@
# The slow solution # Slow solution
We can calculate all possible subsums. We can calculate all possible subsums.
@ -67,7 +67,7 @@ Let's walk the array and keep the current partial sum of elements in the variabl
If the description is too vague, please see the code, it's short enough: If the description is too vague, please see the code, it's short enough:
```js run ```js run demo
function getMaxSubSum(arr) { function getMaxSubSum(arr) {
let maxSum = 0; let maxSum = 0;
let partialSum = 0; let partialSum = 0;

View file

@ -1,8 +1,10 @@
function camelize(str) { function camelize(str) {
return str return str
.split('-') // my-long-word -> ['my', 'long', 'word'] .split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
.map( .map(
// capitalizes first letters of all array items except the first one
// converts ['my', 'long', 'word'] into ['my', 'Long', 'Word']
(word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1) (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
) // ['my', 'long', 'word'] -> ['my', 'Long', 'Word'] )
.join(''); // ['my', 'Long', 'Word'] -> myLongWord .join(''); // joins ['my', 'Long', 'Word'] into 'myLongWord'
} }

View file

@ -2,7 +2,7 @@ Let's walk the array items:
- For each item we'll check if the resulting array already has that item. - For each item we'll check if the resulting array already has that item.
- If it is so, then ignore, otherwise add to results. - If it is so, then ignore, otherwise add to results.
```js run ```js run demo
function unique(arr) { function unique(arr) {
let result = []; let result = [];

View file

@ -1,4 +1,4 @@
``` js run ```js run demo
function filterRange(arr, a, b) { function filterRange(arr, a, b) {
// added brackets around the expression for better readability // added brackets around the expression for better readability
return arr.filter(item => (a <= item && item <= b)); return arr.filter(item => (a <= item && item <= b));

View file

@ -1,5 +1,4 @@
function filterRangeInPlace(arr, a, b) { function filterRangeInPlace(arr, a, b) {
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {

View file

@ -1,4 +1,4 @@
``` js run ```js run demo
function filterRangeInPlace(arr, a, b) { function filterRangeInPlace(arr, a, b) {
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
@ -18,5 +18,4 @@ let arr = [5, 3, 8, 1];
filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4 filterRangeInPlace(arr, 1, 4); // removed the numbers except from 1 to 4
alert( arr ); // [3, 1] alert( arr ); // [3, 1]
``` ```

View file

@ -59,7 +59,7 @@ Here we could also use a plain object instead of the `Map`, because keys are str
That's how the solution can look: That's how the solution can look:
```js run ```js run demo
function aclean(arr) { function aclean(arr) {
let obj = {}; let obj = {};

View file

@ -1,4 +1,4 @@
```js run ```js run demo
function sumSalaries(salaries) { function sumSalaries(salaries) {
let sum = 0; let sum = 0;
@ -8,7 +8,22 @@ function sumSalaries(salaries) {
return sum; // 650 return sum; // 650
} }
let salaries = {
"John": 100,
"Pete": 300,
"Mary": 250
};
alert( sumSalaries(salaries) ); // 650
``` ```
Or, optionally, we could also get the sum using `Object.values` and `reduce`: Or, optionally, we could also get the sum using `Object.values` and `reduce`:
`Object.values(salaries).reduce((a, b) => a + b) // 650` ```js
// reduce loops over array of salaries,
// adding them up
// and returns the result
function sumSalaries(salaries) {
return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
}
```

View file

@ -2,7 +2,7 @@ The method `date.getDay()` returns the number of the weekday, starting from sund
Let's make an array of weekdays, so that we can get the proper day name by its number: Let's make an array of weekdays, so that we can get the proper day name by its number:
```js run ```js run demo
function getWeekDay(date) { function getWeekDay(date) {
let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA']; let days = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];

View file

@ -1,14 +0,0 @@
```js run
function getLocalDay(date) {
let day = date.getDay();
if (day == 0) { // 0 becomes 7
day = 7;
}
return day;
}
alert( getLocalDay(new Date(2012, 0, 3)) ); // 2
```

View file

@ -11,7 +11,7 @@ function getDateAgo(date, days) {
To implement it let's clone the date, like this: To implement it let's clone the date, like this:
```js run ```js run demo
function getDateAgo(date, days) { function getDateAgo(date, days) {
let dateCopy = new Date(date); let dateCopy = new Date(date);

View file

@ -1,5 +1,5 @@
Let's create a date using the next month, but pass zero as the day: Let's create a date using the next month, but pass zero as the day:
```js run ```js run demo
function getLastDayOfMonth(year, month) { function getLastDayOfMonth(year, month) {
let date = new Date(year, month + 1, 0); let date = new Date(year, month + 1, 0);
return date.getDate(); return date.getDate();

View file

@ -1,6 +1,6 @@
To get the time from `date` till now -- let's substract the dates. To get the time from `date` till now -- let's substract the dates.
```js run ```js run demo
function formatDate(date) { function formatDate(date) {
let diff = new Date() - date; // the difference in milliseconds let diff = new Date() - date; // the difference in milliseconds

View file

@ -14,7 +14,7 @@ alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
# Filter inArray # Filter inArray
```js run ```js run demo
function inArray(arr) { function inArray(arr) {
return function(x) { return function(x) {
return arr.includes(x); return arr.includes(x);

View file

@ -55,9 +55,9 @@ function makeArmy() {
As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`. As a result, all `shooter` functions get from the outer lexical envrironment the same, last value `i=10`.
The fix can be very simple: We can fix it by moving the variable definition into the loop:
```js run ```js run demo
function makeArmy() { function makeArmy() {
let shooters = []; let shooters = [];
@ -80,9 +80,9 @@ army[0](); // 0
army[5](); // 5 army[5](); // 5
``` ```
Now it works correctly, because every time the code block in `for (..) {...}` is executed, a new Lexical Environment is created for it, with the corresponding value of `i`. Now it works correctly, because every time the code block in `for (let i=0...) {...}` is executed, a new Lexical Environment is created for it, with the corresponding variable `i`.
So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. A `shooter` gets the value exactly from the one where it was created. So, the value of `i` now lives a little bit closer. Not in `makeArmy()` Lexical Environment, but in the Lexical Environment that corresponds the current loop iteration. That's why now it works.
![](lexenv-makearmy.png) ![](lexenv-makearmy.png)
@ -90,7 +90,6 @@ Here we rewrote `while` into `for`.
Another trick could be possible, let's see it for better understanding of the subject: Another trick could be possible, let's see it for better understanding of the subject:
```js run ```js run
function makeArmy() { function makeArmy() {
let shooters = []; let shooters = [];

View file

@ -1,6 +1,6 @@
The solution: The solution:
```js ```js run demo
function delay(f, ms) { function delay(f, ms) {
return function() { return function() {
@ -8,20 +8,25 @@ function delay(f, ms) {
}; };
} }
let f1000 = delay(alert, 1000);
f1000("test"); // shows "test" after 1000ms
``` ```
Please note how an arrow function is used here. As we know, arrow functions do not have own `this` and `arguments`, so `f.apply(this, arguments)` takes `this` and `arguments` from the wrapper. Please note how an arrow function is used here. As we know, arrow functions do not have own `this` and `arguments`, so `f.apply(this, arguments)` takes `this` and `arguments` from the wrapper.
If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (in-browser), so we'd need to write a bit more code to pass them from the wrapper: If we pass a regular function, `setTimeout` would call it without arguments and `this=window` (assuming we're in the browser).
We still can pass the right `this` by using an intermediate variable, but that's a little bit more cumbersome:
```js ```js
function delay(f, ms) { function delay(f, ms) {
// added variables to pass this and arguments from the wrapper inside setTimeout
return function(...args) { return function(...args) {
let savedThis = this; let savedThis = this; // store this into an intermediate variable
setTimeout(function() { setTimeout(function() {
f.apply(savedThis, args); f.apply(savedThis, args); // use it here
}, ms); }, ms);
}; };

View file

@ -1,6 +1,4 @@
```js demo
```js run no-beautify
function debounce(f, ms) { function debounce(f, ms) {
let isCooldown = false; let isCooldown = false;
@ -18,7 +16,7 @@ function debounce(f, ms) {
} }
``` ```
The call to `debounce` returns a wrapper. There may be two states: A call to `debounce` returns a wrapper. There may be two states:
- `isCooldown = false` -- ready to run. - `isCooldown = false` -- ready to run.
- `isCooldown = true` -- waiting for the timeout. - `isCooldown = true` -- waiting for the timeout.

View file

@ -1,4 +1,4 @@
```js ```js demo
function throttle(func, ms) { function throttle(func, ms) {
let isThrottled = false, let isThrottled = false,