make sure a solution always shows up, use "demo" if exists
This commit is contained in:
parent
360be9ed99
commit
408ba7d4e4
25 changed files with 59 additions and 95 deletions
|
@ -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;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
@ -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);
|
|
||||||
```
|
|
|
@ -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() );
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
```js run demo
|
```js run demo
|
||||||
function Calculator() {
|
function Calculator() {
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
```js run
|
|
||||||
function extractCurrencyValue(str) {
|
|
||||||
return +str.slice(1);
|
|
||||||
}
|
|
||||||
```
|
|
|
@ -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;
|
||||||
|
|
|
@ -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'
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = [];
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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++) {
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -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'];
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
```
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -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 = [];
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
```js
|
```js demo
|
||||||
function throttle(func, ms) {
|
function throttle(func, ms) {
|
||||||
|
|
||||||
let isThrottled = false,
|
let isThrottled = false,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue