Что можно передавать в функцию в качестве параметра?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Легкий
#JavaScript #функции #База JS

Краткий ответ

В JavaScript в функцию можно передавать любые типы данных:

  • Примитивы: числа, строки, boolean, null, undefined, symbol, bigint
  • Объекты: массивы, объекты, даты, регулярные выражения
  • Функции: как обычные функции, так и стрелочные
  • Классы и конструкторы

Все параметры передаются по значению, но для объектов передается ссылка на объект.


Подробное сравнение

Тип параметраСпособ передачиМожно изменитьПример
ПримитивыПо значениюНетfunction(5, "text", true)
ОбъектыПо ссылкеДаfunction({name: "Alex"})
МассивыПо ссылкеДаfunction([1, 2, 3])
ФункцииПо ссылкеДаfunction(callback)
КлассыПо ссылкеДаfunction(MyClass)

Что такое передача по значению и по ссылке?

Передача по значению — создается копия значения, изменения внутри функции не влияют на оригинал.

Передача по ссылке — передается ссылка на объект, изменения внутри функции влияют на оригинал.

// Примитив - по значению
function changePrimitive(num) {
  num = 100;
}
let x = 5;
changePrimitive(x);
console.log(x); // 5 (не изменился)
 
// Объект - по ссылке
function changeObject(obj) {
  obj.name = "Изменено";
}
let user = { name: "Александр" };
changeObject(user);
console.log(user.name); // "Изменено"

Примеры

Примитивные типы

function processData(number, text, flag, empty, undef) {
  console.log(typeof number); // "number"
  console.log(typeof text);   // "string"
  console.log(typeof flag);   // "boolean"
  console.log(typeof empty);  // "object" (null)
  console.log(typeof undef);  // "undefined"
}
 
processData(42, "Привет", true, null, undefined);

Объекты и массивы

function handleData(user, numbers, date) {
  console.log(user.name);        // "Александр"
  console.log(numbers.length);   // 3
  console.log(date.getFullYear()); // текущий год
  
  // Изменяем объект
  user.age = 30;
  numbers.push(4);
}
 
let person = { name: "Александр" };
let arr = [1, 2, 3];
let now = new Date();
 
handleData(person, arr, now);
console.log(person.age);  // 30 (изменился!)
console.log(arr.length);  // 4 (изменился!)

Функции как параметры (колбэки)

function processArray(array, callback) {
  const result = [];
  for (let item of array) {
    result.push(callback(item));
  }
  return result;
}
 
// Передаем функцию как параметр
const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, x => x * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
 
// Передаем именованную функцию
function square(x) {
  return x * x;
}
const squared = processArray(numbers, square);
console.log(squared); // [1, 4, 9, 16, 25]

Классы и конструкторы

class User {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    return `Привет, я ${this.name}!`;
  }
}
 
function createInstance(Constructor, ...args) {
  return new Constructor(...args);
}
 
// Передаем класс как параметр
const user = createInstance(User, "Александр");
console.log(user.greet()); // "Привет, я Александр!"
 
// Передаем встроенный конструктор
const date = createInstance(Date, 2024, 0, 1);
console.log(date.getFullYear()); // 2024

Особые случаи

Деструктуризация параметров

// Деструктуризация объекта
function greetUser({ name, age = 18 }) {
  return `Привет, ${name}! Тебе ${age} лет.`;
}
 
const user = { name: "Александр", age: 30 };
console.log(greetUser(user)); // "Привет, Александр! Тебе 30 лет."
 
// Деструктуризация массива
function processCoordinates([x, y, z = 0]) {
  return { x, y, z };
}
 
const coords = [10, 20];
console.log(processCoordinates(coords)); // { x: 10, y: 20, z: 0 }

Rest параметры

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
 
console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(10, 20));        // 30
 
// Смешанные параметры
function logMessage(level, ...messages) {
  console.log(`[${level}]:`, ...messages);
}
 
logMessage("INFO", "Пользователь", "вошел", "в систему");
// [INFO]: Пользователь вошел в систему

Значения по умолчанию

function createUser(name = "Аноним", age = 18, isActive = true) {
  return { name, age, isActive };
}
 
console.log(createUser());                    // { name: "Аноним", age: 18, isActive: true }
console.log(createUser("Александр"));         // { name: "Александр", age: 18, isActive: true }
console.log(createUser("Мария", 25, false)); // { name: "Мария", age: 25, isActive: false }

Задачи для практики

Задача 1: Что выведет консоль?

function modifyValues(a, b) {
  a = 100;
  b.value = 100;
}
 
let num = 5;
let obj = { value: 5 };
 
modifyValues(num, obj);
console.log(num, obj.value);
Ответ 5 и 100 — примитив `num` не изменился (передача по значению), а свойство объекта `obj.value` изменилось (передача по ссылке).

Задача 2: Что произойдет?

function processArray(arr) {
  arr = [1, 2, 3];
  return arr;
}
 
let original = [4, 5, 6];
let result = processArray(original);
console.log(original, result);
Ответ [4, 5, 6] и [1, 2, 3] — переприсваивание параметра `arr` не влияет на оригинальный массив, создается новый массив.

Задача 3: Что выведет консоль?

function test(callback) {
  return callback(10, 20);
}
 
const result = test((a, b) => a + b);
console.log(result);
Ответ 30 — стрелочная функция `(a, b) => a + b` передается как параметр и вызывается с аргументами 10 и 20.

Задача 4: Что произойдет?

function createObjects(Constructor, count) {
  const objects = [];
  for (let i = 0; i < count; i++) {
    objects.push(new Constructor(`Object ${i}`));
  }
  return objects;
}
 
class Item {
  constructor(name) {
    this.name = name;
  }
}
 
const items = createObjects(Item, 3);
console.log(items.length);
Ответ 3 — класс `Item` передается как параметр, создается 3 экземпляра класса.

Задача 5: Что выведет консоль?

function greet({ name, age = 25 }) {
  return `${name} (${age} лет)`;
}
 
console.log(greet({ name: "Александр" }));
console.log(greet({ name: "Мария", age: 30 }));
Ответ "Александр (25 лет)" и "Мария (30 лет)" — деструктуризация с значением по умолчанию для `age`.

Задача 6: Что произойдет?

function calculate(...numbers) {
  return numbers.filter(n => typeof n === 'number').reduce((sum, n) => sum + n, 0);
}
 
console.log(calculate(1, "2", 3, null, 4, undefined, 5));
Ответ 13 — rest параметры собирают все аргументы в массив, фильтруются только числа (1, 3, 4, 5), их сумма равна 13.

Практические советы

1. Используйте деструктуризацию для объектов

// Плохо
function createUser(userObj) {
  const name = userObj.name;
  const age = userObj.age;
  const email = userObj.email;
  // ...
}
 
// Хорошо
function createUser({ name, age, email }) {
  // сразу доступны name, age, email
}

2. Устанавливайте значения по умолчанию

function processData(data = [], options = {}) {
  const { sort = true, limit = 10 } = options;
  // безопасная работа с параметрами
}

3. Будьте осторожны с мутацией объектов

// Если не хотите изменять оригинал
function processArray(arr) {
  const copy = [...arr]; // создаем копию
  copy.push('новый элемент');
  return copy;
}
 
// Для объектов
function updateUser(user) {
  return { ...user, lastUpdated: new Date() }; // возвращаем новый объект
}

Резюме

В JavaScript в функцию можно передавать любые типы данных:

  • Примитивы передаются по значению (копируются)
  • Объекты передаются по ссылке (можно изменять)
  • Функции можно передавать как колбэки
  • Классы можно передавать как конструкторы

Важно помнить:

  • Изменение примитивов внутри функции не влияет на оригинал
  • Изменение свойств объектов влияет на оригинал
  • Переприсваивание параметра не влияет на оригинальную переменную

Понимание того, что и как можно передавать в функции — это основа для написания гибкого и переиспользуемого кода!


Хочешь больше статей по подготовке к собеседованию? Подпишись на EasyAdvice(@AleksandrEmolov_EasyAdvice), добавляй сайт в избранное и прокачивай себя каждый день 💪