Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions modules/40-define-functions/460-modules/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
@ test.sh
38 changes: 38 additions & 0 deletions modules/40-define-functions/460-modules/description.es.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---

name: Módulos
theory: |

Mientras un programa es pequeño, todo el código cabe en un solo archivo. Pero con el tiempo el programa crece, y orientarse en un único archivo se vuelve difícil. Para dividir el código en partes lógicas, en JavaScript se usan los módulos: un archivo de código independiente es un módulo.

Un módulo decide qué entregar al exterior con la palabra clave `export`, y otro archivo lo conecta mediante `import`:

```javascript
import { length } from 'hexlet-basics/string';

console.log(length('Hello!')); // => 6
```

De un mismo módulo se pueden importar varios nombres a la vez:

```javascript
import { reverse, toUpperCase } from 'hexlet-basics/string';

console.log(reverse('hexlet')); // => telxeh
console.log(toUpperCase('hexlet')); // => HEXLET
```

instructions: |

Implementa la función `mirror()`. Recibe una cadena, la invierte y la convierte a mayúsculas, y devuelve el resultado.

Usa las funciones `reverse()` y `toUpperCase()` del módulo `hexlet-basics/string`. Escribe la importación tú mismo.

```javascript
mirror('hello'); // => 'OLLEH'
mirror('Hexlet'); // => 'TELXEH'
```

tips:
- |
[Documentación sobre módulos (import/export)](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Modules)
13 changes: 13 additions & 0 deletions modules/40-define-functions/460-modules/en/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Implement the `mirror()` function. It takes a string, reverses it, and converts it to upper case, then returns the result.

Use the `reverse()` and `toUpperCase()` functions from the `hexlet-basics/string` module. You need to write the import yourself.

```javascript
mirror('hello'); // => 'OLLEH'
mirror('Hexlet'); // => 'TELXEH'
```

## Hint

* At the beginning of the file, import the functions you need: `import { reverse, toUpperCase } from 'hexlet-basics/string';`
* First reverse the string, then convert the result to upper case
83 changes: 83 additions & 0 deletions modules/40-define-functions/460-modules/en/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
As long as a program is small, all the code can live in a single file. This approach is convenient for simple examples and small tasks. But over time a program starts to grow. When there is a lot of code, it becomes hard to navigate a single file. Real applications consist of tens of thousands of lines (at least) and hundreds of files.

To split a program into separate logical parts, JavaScript uses modules. A separate file with code is a module. The language provides mechanisms that let one file use functions and constants from another.

## export and import

A module decides what to expose. The `export` keyword is used for this. Another file pulls in what was exported via `import`.

You have probably already seen lines like this at the beginning of some exercises — now let's figure out what they mean:

```javascript
import { length } from 'hexlet-basics/string';

console.log(length('Hello!')); // => 6
```

This line connects the `length` function from the `hexlet-basics/string` module and makes it available in the current file.

## Named imports

You can import several names from one module at once by listing them in curly braces:

```javascript
import { reverse, toUpperCase } from 'hexlet-basics/string';

console.log(reverse('hexlet')); // => telxeh
console.log(toUpperCase('hexlet')); // => HEXLET
```

After such an import, you call the functions directly, by their names. This is convenient: you don't have to specify which module a function came from every time.

## Default export

To export something, a module marks it with the word `export`. There are two kinds of export. A named one — there can be as many exported names as you like:

```javascript
// string.js
const reverse = (s) => s.split('').reverse().join('');
const length = (s) => s.length;

export { reverse, length };
```

And a default export — a module can have only one of those. You have already come across it when defining functions:

```javascript
// sum.js
const sum = (a, b) => a + b;

export default sum;
```

A default import is written without curly braces, and you may pick any name for it:

```javascript
import sum from './sum.js';

console.log(sum(2, 3)); // => 5
```

## Renaming on import

Sometimes a name from a module is already taken in the current file. To avoid a conflict, an import can be renamed with `as`:

```javascript
import { reverse as reverseString } from 'hexlet-basics/string';

console.log(reverseString('hexlet')); // => telxeh
```

Now the function is available under the name `reverseString`, while the original name `reverse` stays free.

## Standard modules

Every language ships with a set of ready-made functions. In JavaScript, most of them are available globally and need no import — for example, the `Math` object for math or `console` for output.

But JavaScript runs in different environments. The Node.js server environment has built-in modules that need to be imported. They are imported with the `node:` prefix — for example, the `node:fs` module for working with files:

```javascript
import { readFile } from 'node:fs/promises';
```

Ready-made functions can be taken not only from standard modules but also from third-party ones. We'll talk about how those are distributed in the next lesson.
5 changes: 5 additions & 0 deletions modules/40-define-functions/460-modules/en/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
name: Modules
tips:
- |
[Documentation on modules (import/export)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
13 changes: 13 additions & 0 deletions modules/40-define-functions/460-modules/es/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Implementa la función `mirror()`. Recibe una cadena, la invierte y la convierte a mayúsculas, y luego devuelve el resultado.

Usa las funciones `reverse()` y `toUpperCase()` del módulo `hexlet-basics/string`. Debes escribir la importación tú mismo.

```javascript
mirror('hello'); // => 'OLLEH'
mirror('Hexlet'); // => 'TELXEH'
```

## Pista

* Al comienzo del archivo, importa las funciones que necesitas: `import { reverse, toUpperCase } from 'hexlet-basics/string';`
* Primero invierte la cadena y luego convierte el resultado a mayúsculas
83 changes: 83 additions & 0 deletions modules/40-define-functions/460-modules/es/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
Mientras un programa es pequeño, todo el código puede vivir en un solo archivo. Este enfoque es cómodo para ejemplos sencillos y tareas pequeñas. Pero con el tiempo el programa empieza a crecer. Cuando hay mucho código, resulta difícil orientarse en un único archivo. Las aplicaciones reales constan de decenas de miles de líneas (como mínimo) y cientos de archivos.

Para dividir un programa en partes lógicas separadas, en JavaScript se usan los módulos. Un archivo de código independiente es un módulo. El lenguaje proporciona mecanismos con los que un archivo puede usar funciones y constantes de otro.

## export e import

El módulo decide qué entregar al exterior. Para ello se usa la palabra clave `export`. Otro archivo conecta lo exportado mediante `import`.

Probablemente ya hayas visto líneas como esta al comienzo de algunos ejercicios — ahora veamos qué significan:

```javascript
import { length } from 'hexlet-basics/string';

console.log(length('Hello!')); // => 6
```

Esta línea conecta la función `length` del módulo `hexlet-basics/string` y la hace disponible en el archivo actual.

## Importación con nombre

De un mismo módulo se pueden importar varios nombres a la vez, enumerándolos entre llaves:

```javascript
import { reverse, toUpperCase } from 'hexlet-basics/string';

console.log(reverse('hexlet')); // => telxeh
console.log(toUpperCase('hexlet')); // => HEXLET
```

Tras esta importación, las funciones se llaman directamente, por sus nombres. Esto es cómodo: no hace falta indicar cada vez de qué módulo proviene una función.

## Exportación por defecto

Para exportar algo, el módulo lo marca con la palabra `export`. Hay dos tipos de exportación. La nombrada: puede haber tantos nombres exportados como se quiera:

```javascript
// string.js
const reverse = (s) => s.split('').reverse().join('');
const length = (s) => s.length;

export { reverse, length };
```

Y la exportación por defecto: un módulo solo puede tener una. Ya te has topado con ella al definir funciones:

```javascript
// sum.js
const sum = (a, b) => a + b;

export default sum;
```

La importación por defecto se escribe sin llaves, y se le puede dar cualquier nombre:

```javascript
import sum from './sum.js';

console.log(sum(2, 3)); // => 5
```

## Renombrar al importar

A veces un nombre de un módulo ya está ocupado en el archivo actual. Para evitar el conflicto, la importación se puede renombrar con `as`:

```javascript
import { reverse as reverseString } from 'hexlet-basics/string';

console.log(reverseString('hexlet')); // => telxeh
```

Ahora la función está disponible bajo el nombre `reverseString`, mientras que el nombre original `reverse` queda libre.

## Módulos estándar

Cada lenguaje viene con un conjunto de funciones listas para usar. En JavaScript, la mayoría de ellas están disponibles de forma global y no requieren importación — por ejemplo, el objeto `Math` para las matemáticas o `console` para la salida.

Pero JavaScript se ejecuta en distintos entornos. El entorno de servidor Node.js tiene módulos integrados que hay que importar. Se importan con el prefijo `node:` — por ejemplo, el módulo `node:fs` para trabajar con archivos:

```javascript
import { readFile } from 'node:fs/promises';
```

Las funciones listas se pueden tomar no solo de los módulos estándar, sino también de módulos de terceros. Hablaremos de cómo se distribuyen estos en la siguiente lección.
5 changes: 5 additions & 0 deletions modules/40-define-functions/460-modules/es/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
name: Módulos
tips:
- |
[Documentación sobre módulos (import/export)](https://developer.mozilla.org/es/docs/Web/JavaScript/Guide/Modules)
7 changes: 7 additions & 0 deletions modules/40-define-functions/460-modules/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// BEGIN
import { reverse, toUpperCase } from 'hexlet-basics/string';

const mirror = (text) => toUpperCase(reverse(text));
// END

export default mirror;
13 changes: 13 additions & 0 deletions modules/40-define-functions/460-modules/ru/EXERCISE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Реализуйте функцию `mirror()`. Она принимает строку, переворачивает её и переводит в верхний регистр, после чего возвращает результат.

Используйте функции `reverse()` и `toUpperCase()` из модуля `hexlet-basics/string`. Импорт нужно написать самостоятельно.

```javascript
mirror('hello'); // => 'OLLEH'
mirror('Hexlet'); // => 'TELXEH'
```

## Подсказка

* В начале файла импортируйте нужные функции: `import { reverse, toUpperCase } from 'hexlet-basics/string';`
* Сначала переверните строку, затем переведите результат в верхний регистр
83 changes: 83 additions & 0 deletions modules/40-define-functions/460-modules/ru/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
Пока программа маленькая, весь код можно хранить в одном файле. Такой подход удобен для простых примеров и небольших задач. Но со временем программа начинает расти. Когда кода становится много, ориентироваться в одном файле становится сложно. Реальные приложения состоят из десятков тысяч строк (как минимум) и сотен файлов.

Чтобы разделить программу на отдельные логические части, в JavaScript используют модули. Отдельный файл с кодом и есть модуль. А язык предоставляет механизмы, с помощью которых один файл может использовать функции и константы из другого.

## export и import

Модуль сам решает, что отдать наружу. Для этого используют ключевое слово `export`. Другой файл подключает экспортированное через `import`.

Скорее всего, такие строки вы уже видели в начале некоторых заданий — теперь разберёмся, что они значат:

```javascript
import { length } from 'hexlet-basics/string';

console.log(length('Hello!')); // => 6
```

Эта строчка подключает функцию `length` из модуля `hexlet-basics/string` и делает её доступной в текущем файле.

## Именованный импорт

Из одного модуля можно импортировать сразу несколько имён, перечислив их в фигурных скобках:

```javascript
import { reverse, toUpperCase } from 'hexlet-basics/string';

console.log(reverse('hexlet')); // => telxeh
console.log(toUpperCase('hexlet')); // => HEXLET
```

После такого импорта к функциям обращаются напрямую, по их именам. Это удобно: не нужно каждый раз писать, из какого модуля взята функция.

## Экспорт по умолчанию

Чтобы что-то экспортировать, модуль помечает это словом `export`. Экспорт бывает двух видов. Именованный — экспортируемых имён может быть сколько угодно:

```javascript
// string.js
const reverse = (s) => s.split('').reverse().join('');
const length = (s) => s.length;

export { reverse, length };
```

И экспорт по умолчанию — он в модуле может быть только один. С таким экспортом вы уже сталкивались, когда определяли функции:

```javascript
// sum.js
const sum = (a, b) => a + b;

export default sum;
```

Импорт по умолчанию пишется без фигурных скобок, и имя при импорте можно выбрать любое:

```javascript
import sum from './sum.js';

console.log(sum(2, 3)); // => 5
```

## Переименование при импорте

Иногда имя из модуля уже занято в текущем файле. Чтобы избежать конфликта, импорт можно переименовать через `as`:

```javascript
import { reverse as reverseString } from 'hexlet-basics/string';

console.log(reverseString('hexlet')); // => telxeh
```

Теперь функция доступна под именем `reverseString`, а исходное имя `reverse` остаётся свободным.

## Стандартные модули

У каждого языка есть набор готовых функций. В JavaScript бо́льшая часть из них доступна глобально и импорта не требует — например, объект `Math` для математики или `console` для вывода.

Но JavaScript исполняется в разных средах. В серверном окружении Node.js есть встроенные модули, которые нужно подключать. Их подключают с префиксом `node:` — например, модуль `node:fs` для работы с файлами:

```javascript
import { readFile } from 'node:fs/promises';
```

Готовые функции можно брать не только из стандартных, но и из сторонних модулей. О том, как они распространяются, поговорим в следующем уроке.
5 changes: 5 additions & 0 deletions modules/40-define-functions/460-modules/ru/data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
name: Модули
tips:
- |
[Документация по модулям (import/export)](https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Modules)
9 changes: 9 additions & 0 deletions modules/40-define-functions/460-modules/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @ts-check

import { expect, test } from 'vitest';
import mirror from './index.js';

test('mirror', () => {
expect(mirror('hello')).toBe('OLLEH');
expect(mirror('Hexlet')).toBe('TELXEH');
});
2 changes: 2 additions & 0 deletions modules/40-define-functions/470-packages/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
test:
@ test.sh
Loading
Loading