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.
```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
```js run demo solution
let calculator = {
sum() {
return this.a + this.b;
@ -20,4 +19,3 @@ calculator.read();
alert( calculator.sum() );
alert( calculator.mul() );
```

View file

@ -1,6 +1,6 @@
The solution is to return the object itself from every call.
```js run
```js run demo
let ladder = {
step: 0,
up() {
@ -28,7 +28,7 @@ ladder.up().up().down().up().down().showStep(); // 1
We also can write a single call per line. For long chains it's more readable:
```js
```js
ladder
.up()
.up()
@ -37,4 +37,3 @@ ladder
.down()
.showStep(); // 1
```

View file

@ -1,5 +1,3 @@
```js run demo
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.
```js run
```js run demo
function truncate(str, maxlength) {
return (str.length > maxlength) ?
return (str.length > maxlength) ?
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.
@ -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:
```js run
```js run demo
function getMaxSubSum(arr) {
let maxSum = 0;
let partialSum = 0;

View file

@ -1,8 +1,10 @@
function camelize(str) {
return str
.split('-') // my-long-word -> ['my', 'long', 'word']
.map(
.split('-') // splits 'my-long-word' into array ['my', 'long', 'word']
.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)
) // ['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.
- If it is so, then ignore, otherwise add to results.
```js run
```js run demo
function unique(arr) {
let result = [];

View file

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

View file

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

View file

@ -1,4 +1,4 @@
``` js run
```js run demo
function filterRangeInPlace(arr, a, b) {
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
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:
```js run
```js run demo
function aclean(arr) {
let obj = {};

View file

@ -1,4 +1,4 @@
```js run
```js run demo
function sumSalaries(salaries) {
let sum = 0;
@ -8,7 +8,22 @@ function sumSalaries(salaries) {
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`:
`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:
```js run
```js run demo
function getWeekDay(date) {
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:
```js run
```js run demo
function getDateAgo(date, days) {
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:
```js run
```js run demo
function getLastDayOfMonth(year, month) {
let date = new Date(year, month + 1, 0);
return date.getDate();

View file

@ -1,6 +1,6 @@
To get the time from `date` till now -- let's substract the dates.
```js run
```js run demo
function formatDate(date) {
let diff = new Date() - date; // the difference in milliseconds
@ -57,12 +57,12 @@ function formatDate(date) {
let diffSec = Math.round(diffMs / 1000);
let diffMin = diffSec / 60;
let diffHour = diffMin / 60;
// formatting
year = year.toString().slice(-2);
month = month < 10 ? '0' + month : month;
dayOfMonth = dayOfMonth < 10 ? '0' + dayOfMonth : dayOfMonth;
if (diffSec < 1) {
return 'right now';
} else if (diffMin < 1) {

View file

@ -14,7 +14,7 @@ alert( arr.filter(inBetween(3, 6)) ); // 3,4,5,6
# Filter inArray
```js run
```js run demo
function inArray(arr) {
return function(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`.
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() {
let shooters = [];
@ -80,9 +80,9 @@ army[0](); // 0
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)
@ -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:
```js run
function makeArmy() {
let shooters = [];

View file

@ -1,6 +1,6 @@
The solution:
```js
```js run demo
function delay(f, ms) {
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.
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
function delay(f, ms) {
// added variables to pass this and arguments from the wrapper inside setTimeout
return function(...args) {
let savedThis = this;
let savedThis = this; // store this into an intermediate variable
setTimeout(function() {
f.apply(savedThis, args);
f.apply(savedThis, args); // use it here
}, ms);
};

View file

@ -1,6 +1,4 @@
```js run no-beautify
```js demo
function debounce(f, ms) {
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 = true` -- waiting for the timeout.

View file

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