Skip to content

Commit 276065b

Browse files
committed
ok
1 parent 8bf36b7 commit 276065b

File tree

29 files changed

+715
-71
lines changed

29 files changed

+715
-71
lines changed

1-js/7-deeper/6-bind/6-ask-currying/task.md

Lines changed: 0 additions & 58 deletions
This file was deleted.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function makeLogging(f, log) {
2+
3+
function wrapper(a) {
4+
log.push(a);
5+
return f.call(this, a);
6+
}
7+
8+
return wrapper;
9+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
describe("makeLogging", function() {
2+
it("записывает вызовы в массив log", function() {
3+
var work = sinon.spy();
4+
5+
var log = [];
6+
work = makeLogging(work, log);
7+
assert.deepEqual(log, []);
8+
9+
work(1);
10+
assert.deepEqual(log, [1]);
11+
12+
work(2);
13+
assert.deepEqual(log, [1, 2]);
14+
});
15+
16+
it("передаёт вызов функции, возвращает её результат", function() {
17+
var log = [];
18+
19+
function work(x) {
20+
return x * 2;
21+
}
22+
23+
work = sinon.spy(work);
24+
var spy = work;
25+
work = makeLogging(work, log);
26+
27+
assert.equal(work(1), 2);
28+
assert(spy.calledWith(1));
29+
});
30+
31+
32+
it("сохраняет контекст вызова для методов объекта", function() {
33+
var log = [];
34+
35+
var calculator = {
36+
double: function(x) {
37+
return x * 2;
38+
}
39+
}
40+
41+
calculator.double = sinon.spy(calculator.double);
42+
var spy = calculator.double;
43+
calculator.double = makeLogging(calculator.double, log);
44+
45+
assert.equal(calculator.double(1), 2);
46+
assert(spy.calledWith(1));
47+
assert(spy.calledOn(calculator));
48+
});
49+
50+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Возвратим декоратор `wrapper` который будет записывать аргумент в `log` и передавать вызов в `f`:
2+
3+
```js run
4+
function work(a) {
5+
/*...*/ // work - произвольная функция, один аргумент
6+
}
7+
8+
function makeLogging(f, log) {
9+
10+
*!*
11+
function wrapper(a) {
12+
log.push(a);
13+
return f.call(this, a);
14+
}
15+
*/!*
16+
17+
return wrapper;
18+
}
19+
20+
var log = [];
21+
work = makeLogging(work, log);
22+
23+
work(1); // 1
24+
work(5); // 5
25+
26+
for (var i = 0; i < log.length; i++) {
27+
alert( 'Лог:' + log[i] ); // "Лог:1", затем "Лог:5"
28+
}
29+
```
30+
31+
**Обратите внимание, вызов функции осуществляется как `f.call(this, a)`, а не просто `f(a)`.**
32+
33+
Передача контекста необходима, чтобы декоратор корректно работал с методами объекта. Например:
34+
35+
```js
36+
user.method = makeLogging(user.method, log);
37+
```
38+
39+
Теперь при вызове `user.method(...)` в декоратор будет передаваться контекст `this`, который надо передать исходной функции через `call/apply`.
40+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
importance: 5
2+
3+
---
4+
5+
# Логирующий декоратор (1 аргумент)
6+
7+
Создайте декоратор `makeLogging(f, log)`, который берет функцию `f` и массив `log`.
8+
9+
Он должен возвращать обёртку вокруг `f`, которая при каждом вызове записывает ("логирует") аргументы в `log`, а затем передает вызов в `f`.
10+
11+
**В этой задаче можно считать, что у функции `f` ровно один аргумент.**
12+
13+
Работать должно так:
14+
15+
```js
16+
function work(a) {
17+
/* ... */ // work - произвольная функция, один аргумент
18+
}
19+
20+
function makeLogging(f, log) { /* ваш код */ }
21+
22+
var log = [];
23+
work = makeLogging(work, log);
24+
25+
work(1); // 1, добавлено в log
26+
work(5); // 5, добавлено в log
27+
28+
for (var i = 0; i < log.length; i++) {
29+
*!*
30+
alert( 'Лог:' + log[i] ); // "Лог:1", затем "Лог:5"
31+
*/!*
32+
}
33+
```
34+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function makeLogging(f, log) {
2+
3+
function wrapper() {
4+
log.push([].slice.call(arguments));
5+
return f.apply(this, arguments);
6+
}
7+
8+
return wrapper;
9+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
describe("makeLogging", function() {
2+
it("записывает вызовы в массив log", function() {
3+
var work = sinon.spy();
4+
5+
var log = [];
6+
work = makeLogging(work, log);
7+
assert.deepEqual(log, []);
8+
9+
work(1, 2);
10+
assert.deepEqual(log, [
11+
[1, 2]
12+
]);
13+
14+
work(3, 4);
15+
assert.deepEqual(log, [
16+
[1, 2],
17+
[3, 4]
18+
]);
19+
});
20+
21+
it("передаёт вызов функции, возвращает её результат", function() {
22+
var log = [];
23+
24+
function sum(a, b) {
25+
return a + b;
26+
}
27+
28+
sum = sinon.spy(sum);
29+
var spy = sum;
30+
sum = makeLogging(sum, log);
31+
32+
assert.equal(sum(1, 2), 3);
33+
assert(spy.calledWith(1, 2));
34+
});
35+
36+
37+
it("сохраняет контекст вызова для методов объекта", function() {
38+
var log = [];
39+
40+
var calculator = {
41+
sum: function(a, b) {
42+
return a + b;
43+
}
44+
}
45+
46+
calculator.sum = sinon.spy(calculator.sum);
47+
var spy = calculator.sum;
48+
calculator.sum = makeLogging(calculator.sum, log);
49+
50+
assert.equal(calculator.sum(1, 2), 3);
51+
assert(spy.calledWith(1, 2));
52+
assert(spy.calledOn(calculator));
53+
});
54+
55+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
Решение аналогично задаче <info:task/logging-decorator>, разница в том, что в лог вместо одного аргумента идет весь объект `arguments`.
2+
3+
Для передачи вызова с произвольным количеством аргументов используем `f.apply(this, arguments)`.
4+
5+
```js run
6+
function work(a, b) {
7+
alert( a + b ); // work - произвольная функция
8+
}
9+
10+
function makeLogging(f, log) {
11+
12+
*!*
13+
function wrapper() {
14+
log.push([].slice.call(arguments));
15+
return f.apply(this, arguments);
16+
}
17+
*/!*
18+
19+
return wrapper;
20+
}
21+
22+
var log = [];
23+
work = makeLogging(work, log);
24+
25+
work(1, 2); // 3
26+
work(4, 5); // 9
27+
28+
for (var i = 0; i < log.length; i++) {
29+
var args = log[i]; // массив из аргументов i-го вызова
30+
alert( 'Лог:' + args.join() ); // "Лог:1,2", "Лог:4,5"
31+
}
32+
```
33+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
importance: 3
2+
3+
---
4+
5+
# Логирующий декоратор (много аргументов)
6+
7+
Создайте декоратор `makeLogging(func, log)`, для функции `func` возвращающий обёртку, которая при каждом вызове добавляет её аргументы в массив `log`.
8+
9+
Условие аналогично задаче <info:task/logging-decorator>, но допускается `func` с любым набором аргументов.
10+
11+
Работать должно так:
12+
13+
```js
14+
function work(a, b) {
15+
alert( a + b ); // work - произвольная функция
16+
}
17+
18+
function makeLogging(f, log) { /* ваш код */ }
19+
20+
var log = [];
21+
work = makeLogging(work, log);
22+
23+
work(1, 2); // 3
24+
work(4, 5); // 9
25+
26+
for (var i = 0; i < log.length; i++) {
27+
var args = log[i]; // массив из аргументов i-го вызова
28+
alert( 'Лог:' + args.join() ); // "Лог:1,2", "Лог:4,5"
29+
}
30+
```
31+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function makeCaching(f) {
2+
var cache = {};
3+
4+
return function(x) {
5+
if (!(x in cache)) {
6+
cache[x] = f.call(this, x);
7+
}
8+
return cache[x];
9+
};
10+
11+
}

0 commit comments

Comments
 (0)