Skip to content

Commit 4dacfcb

Browse files
committed
Update code and links
1 parent 3582d90 commit 4dacfcb

File tree

7 files changed

+263
-2
lines changed

7 files changed

+263
-2
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"responsive-preview": {
3+
"Mobile": [320, 675],
4+
"Tablet": [1024, 765],
5+
"Desktop": [1400, 800],
6+
"Desktop HD": [1920, 1080]
7+
}
8+
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<title>Safe Getter</title>
6+
<meta charset="UTF-8" />
7+
</head>
8+
9+
<body>
10+
<div id="app"></div>
11+
12+
<script src="src/index.js"></script>
13+
14+
<section>
15+
<h2>Задача: Реализация аналога функции <code>_.get</code> из lodash</h2>
16+
17+
<h3>Минимальный набор знаний</h3>
18+
<ul>
19+
<li>
20+
<strong>Доступ к свойствам объекта (через точку и скобки):</strong> - <code>obj.property</code> или <code>obj["property"]</code>.<br>
21+
Квадратные скобки позволяют использовать переменную с именем свойства. <small>Подробнее: <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Working_with_objects" target="_blank">MDN: Работа с объектами</a></small>
22+
</li>
23+
<li>
24+
<strong>Работа с вложенными объектами:</strong> -
25+
Для доступа к свойствам внутри других объектов используйте последовательный доступ: <code>obj.user.profile.name</code> или <code>obj['user']['profile'].name</code> -
26+
<small>Подробнее: <a href="https://learn.javascript.ru/object" target="_blank">learn.javascript.ru: Объекты</a></small>
27+
</li>
28+
<li>
29+
<strong>Работа со строками и массивами:</strong> -
30+
Используйте <a href="https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/split" target="_blank"><code>split()</code></a> для разбивки строки пути на части: <code>'user.profile.name'.split('.')</code>.
31+
</li>
32+
<li>
33+
<strong>Проверка существования свойства:</strong>-
34+
Если обратиться к несуществующему свойству, вернётся <code>undefined</code>. Можно проверить через сравнение с <code>undefined</code> или оператор <code>in</code>: <code>'key' in obj</code>.
35+
<small>Подробнее: <a href="https://learn.javascript.ru/object" target="_blank">learn.javascript.ru: Объекты</a></small>
36+
</li>
37+
<li>
38+
<strong>Условные конструкции:</strong>-
39+
Используйте <code>if</code> для проверки условий, например: если свойство не найдено, вернуть значение по умолчанию.
40+
</li>
41+
<li>
42+
<strong>Объявление функций с несколькими аргументами</strong>
43+
</li>
44+
<li>
45+
<strong>Обработка пустого пути</strong> - как проверить что строка или другое значение "пустое"
46+
</li>
47+
</ul>
48+
49+
50+
51+
<h3>Что нужно сделать</h3>
52+
<p>
53+
Реализуйте функцию <code>get</code>, которая позволяет безопасно получать значения из вложенных объектов по
54+
строковому пути. Эта функция должна работать аналогично методу <a href="https://webdevkin.ru/posts/frontend/lodash-get" target="_blank"><code>_.get</code> из библиотеки lodash</a>.
55+
</p>
56+
<pre><code>
57+
/**
58+
* get: Smart getter for object props
59+
*
60+
* Check tests for usage examples
61+
*
62+
* @param {any} obj
63+
* @param {string} property
64+
* @param {any} fallbackValue
65+
*/
66+
</code></pre>
67+
<table>
68+
<thead>
69+
<tr>
70+
<th>Описание в JSDoc</th>
71+
<th>Пояснение простыми словами</th>
72+
</tr>
73+
</thead>
74+
<tbody>
75+
<tr>
76+
<td><code>get: Smart getter for object props</code></td>
77+
<td>Это функция, которая "умно" достает значения свойств из объекта.</td>
78+
</tr>
79+
<tr>
80+
<td><code>Check tests for usage examples</code></td>
81+
<td>Посмотри тесты, чтобы увидеть примеры использования этой функции.</td>
82+
</tr>
83+
<tr>
84+
<td><code>@param {any} obj</code></td>
85+
<td>Первый аргумент — объект, из которого нужно получить значение.</td>
86+
</tr>
87+
<tr>
88+
<td><code>@param {string} property</code></td>
89+
<td>Второй аргумент — строка с путем к нужному свойству, например: <code>'user.profile.name'</code>.</td>
90+
</tr>
91+
<tr>
92+
<td><code>@param {any} fallbackValue</code></td>
93+
<td>Третий аргумент — значение по умолчанию, которое возвращается, если свойство не найдено.</td>
94+
</tr>
95+
</tbody>
96+
</table>
97+
98+
99+
<h3>Описание задачи</h3>
100+
<ul>
101+
<li>Функция принимает объект, строку с путем до свойства (через точку или скобки, например,
102+
<code>'user.profile.name'</code> или <code>'user["profile"].name'</code>) и значение по умолчанию.</li>
103+
<li>Возвращает значение, найденное по этому пути, либо значение по умолчанию, если путь не существует или где-то
104+
на пути встречается <code>undefined</code> или <code>null</code>.</li>
105+
<li>Если путь пустой, функция должна вернуть сам объект.</li>
106+
</ul>
107+
108+
<h3>Когда <a href="https://medium.com/nuances-of-programming/%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-lodash-%D0%BF%D0%BE-%D0%BF%D1%80%D0%B5%D0%B6%D0%BD%D0%B5%D0%BC%D1%83-%D0%BF%D0%BE%D0%BB%D0%B5%D0%B7%D0%B5%D0%BD-5c6906df9617">бывает полезна</a></h3>
109+
<ul>
110+
<li>Когда структура объекта заранее неизвестна или может быть глубоко вложенной.</li>
111+
<li>Когда нужно избежать ошибок при попытке доступа к несуществующим свойствам (например,
112+
<code>Cannot read property 'x' of undefined'</code>).</li>
113+
<li>Для обработки данных из API, где некоторые поля могут отсутствовать.</li>
114+
</ul>
115+
116+
<h3>Где такая функция уже используется</h3>
117+
<ul>
118+
<li>В библиотеке lodash функция называется <code>_.get</code> и широко применяется для безопасного доступа к
119+
вложенным данным.</li>
120+
<li>Аналогичные функции есть в других библиотеках, например, в Ramda (<code>R.path</code>), а также в различных
121+
утилитах для JavaScript/TypeScript.</li>
122+
</ul>
123+
124+
<h3>Пример использования</h3>
125+
<pre><code class="language-js">
126+
const obj = { user: { profile: { name: 'Ivan' } } };
127+
128+
get(obj, 'user.profile.name', 'No name'); // вернет 'Ivan'
129+
get(obj, 'user.profile.age', 18); // вернет 18
130+
get(obj, 'user.address.city', 'Москва'); // вернет 'Москва'
131+
get(obj, '', 'default'); // вернет весь объект obj
132+
</code></pre>
133+
134+
<p><strong>Ваша задача — реализовать эту функцию самостоятельно, не используя lodash или другие сторонние
135+
библиотеки.</strong></p>
136+
</section>
137+
138+
</body>
139+
140+
</html>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "smart-getter",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.html",
6+
"scripts": {
7+
"start": "parcel index.html --open",
8+
"build": "parcel build index.html"
9+
},
10+
"dependencies": {
11+
"parcel-bundler": "^1.6.1"
12+
},
13+
"devDependencies": {
14+
"@babel/core": "7.2.0"
15+
},
16+
"resolutions": {
17+
"@babel/preset-env": "7.13.8"
18+
},
19+
"keywords": []
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* get: Smart getter for object props
3+
*
4+
* Check tests for usage examples
5+
*
6+
* @param {any} obj
7+
* @param {string} property
8+
* @param {any} fallbackValue
9+
*/
10+
// export function get() {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { get } from "./get";
2+
3+
const getObj = () => ({
4+
a: 1,
5+
b: 2,
6+
c: {
7+
d: 3,
8+
e: 4,
9+
f: [
10+
0,
11+
1,
12+
2,
13+
3,
14+
{
15+
a: 10,
16+
b: 20,
17+
c: {
18+
d: {
19+
e: 30,
20+
},
21+
},
22+
},
23+
],
24+
},
25+
});
26+
27+
describe("get", () => {
28+
const invalidKeys = ["d", "c.z", "x.d", "c.f.100", "c.f.4.x", "z.f.4.b"];
29+
let obj;
30+
beforeEach(() => (obj = getObj()));
31+
32+
it("is a function", () => expect(get).toBeInstanceOf(Function));
33+
34+
it("returns valid properties", () => {
35+
expect(get(obj, "a")).toBe(1);
36+
expect(get(obj, "b")).toBe(2);
37+
expect(get(obj, "c.d")).toBe(3);
38+
expect(get(obj, "c.e")).toBe(4);
39+
expect(get(obj, "c.f.0")).toBe(0);
40+
expect(get(obj, "c.f.1")).toBe(1);
41+
expect(get(obj, "c.f.2")).toBe(2);
42+
expect(get(obj, "c.f.3")).toBe(3);
43+
expect(get(obj, "c.f.4.a")).toBe(10);
44+
expect(get(obj, "c.f.4.b")).toBe(20);
45+
expect(get(obj, "c.f.4.c.d.e")).toBe(30);
46+
});
47+
48+
it("returns undefined for invalid properties", () => {
49+
invalidKeys.forEach((invalidKey) =>
50+
expect(get(obj, invalidKey)).toBe(undefined)
51+
);
52+
});
53+
54+
it("returns fallback value if provided", () => {
55+
invalidKeys.forEach((invalidKey) => {
56+
const fallbackValue = Math.random();
57+
expect(get(obj, invalidKey, fallbackValue)).toBe(fallbackValue);
58+
});
59+
});
60+
61+
it("works not only with objects", () => {
62+
expect(get([1, 2, 3], "1")).toBe(2);
63+
expect(get("hello", "1")).toBe("e");
64+
expect(get(23, "1")).toBe(undefined);
65+
expect(get(null, "1")).toBe(undefined);
66+
expect(get(undefined, "1")).toBe(undefined);
67+
});
68+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// import { get } from "./get";
2+
3+
window.data = {
4+
person: {
5+
name: "Bob",
6+
details: {
7+
age: 18,
8+
catName: "Bars",
9+
},
10+
},
11+
};
12+
13+
document.getElementById("app").innerHTML = `<h1>Getter</h1>`;
14+
15+
// window._get = get;

lessons/lesson06/lesson.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ console.log(settings[b]); // ?
499499

500500
<!-- v -->
501501

502-
[Практика](https://codesandbox.io/s/github/vvscode/otus--javascript-basic/tree/master/lessons/lesson03/code/smart-getter)
502+
[Практика](https://codesandbox.io/s/github/JavaScript-Basic-OTUS/otus--jsbasic/tree/master/lessons/lesson06/code/smart-getter)
503503

504504
Напишите функцию, которая позволит безопасно читать свойства из объекта на любой вложенности.
505505

@@ -511,7 +511,7 @@ console.log(settings[b]); // ?
511511

512512
<!-- s -->
513513

514-
### [Домашнее задание](https://github.com/vvscode/otus--javascript-basic/blob/master/lessons/lesson03/homework_lec1.md)
514+
### [Домашнее задание](https://github.com/JavaScript-Basic-OTUS/otus--jsbasic/blob/master/lessons/lesson06/task.md)
515515

516516
<!-- v -->
517517

0 commit comments

Comments
 (0)