В JavaScript существует 5 основных способов объявления функций:
Ключевые различия:
this
Классический способ объявления функции.
function greet(name) {
return `Привет, ${name}!`;
}
console.log(greet("Александр")); // "Привет, Александр!"
Особенности:
this
// Работает благодаря hoisting!
console.log(sayHello("Мир")); // "Привет, Мир!"
function sayHello(name) {
return `Привет, ${name}!`;
}
Функция как значение переменной.
const greet = function(name) {
return `Привет, ${name}!`;
};
console.log(greet("Александр")); // "Привет, Александр!"
Особенности:
this
// Ошибка! sayHello не определена
// console.log(sayHello("Мир")); // ReferenceError
const sayHello = function(name) {
return `Привет, ${name}!`;
};
// Именованное функциональное выражение
const factorial = function fact(n) {
return n <= 1 ? 1 : n * fact(n - 1);
};
Краткий синтаксис функций, введенный в ES6.
// Обычная стрелочная функция
const greet = (name) => {
return `Привет, ${name}!`;
};
// Краткая запись (неявный return)
const greetShort = name => `Привет, ${name}!`;
// Без параметров
const sayHello = () => "Привет!";
// Несколько параметров
const add = (a, b) => a + b;
console.log(greet("Александр")); // "Привет, Александр!"
console.log(add(5, 3)); // 8
Особенности:
this
— наследует контекстarguments
const obj = {
name: "Александр",
// Обычная функция
regularMethod: function() {
console.log(this.name); // "Александр"
const inner = function() {
console.log(this.name); // undefined (this = window/global)
};
inner();
},
// Стрелочная функция
arrowMethod: function() {
console.log(this.name); // "Александр"
const inner = () => {
console.log(this.name); // "Александр" (наследует this)
};
inner();
}
};
Краткий синтаксис для методов объектов (ES6).
const person = {
name: "Александр",
age: 30,
// Краткий синтаксис метода
greet() {
return `Привет, я ${this.name}!`;
},
// Эквивалентно:
greetOld: function() {
return `Привет, я ${this.name}!`;
}
};
console.log(person.greet()); // "Привет, я Александр!"
Особенности:
this
super
в классахФункция для создания объектов.
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
return `Привет, я ${this.name}!`;
};
}
// Создание объекта
const person = new Person("Александр", 30);
console.log(person.greet()); // "Привет, я Александр!"
// Проверка типа
console.log(person instanceof Person); // true
Особенности:
new
this
указывает на создаваемый объектСпособ | Hoisting | this | Конструктор | Синтаксис |
---|---|---|---|---|
Function Declaration | ✅ Да | Динамический | ✅ Да | function name() {} |
Function Expression | ❌ Нет | Динамический | ✅ Да | const name = function() {} |
Arrow Function | ❌ Нет | Лексический | ❌ Нет | const name = () => {} |
Method Definition | ❌ Нет | Динамический | ✅ Да | methodName() {} |
Constructor Function | ✅ Да | Новый объект | ✅ Да | function Name() {} |
this
в функцияхfunction regularFunction() {
console.log(this); // зависит от способа вызова
}
// Глобальный вызов
regularFunction(); // window (браузер) или global (Node.js)
// Вызов как метод
const obj = { method: regularFunction };
obj.method(); // obj
// Явная привязка
regularFunction.call({ name: "test" }); // { name: "test" }
const arrowFunction = () => {
console.log(this); // всегда лексический контекст
};
const obj = {
name: "Александр",
regularMethod() {
console.log(this.name); // "Александр"
const arrow = () => {
console.log(this.name); // "Александр" (наследует от regularMethod)
};
arrow();
}
};
console.log(typeof foo);
console.log(typeof bar);
function foo() {}
var bar = function() {};
const obj = {
name: "Александр",
regular: function() {
return this.name;
},
arrow: () => {
return this.name;
}
};
console.log(obj.regular());
console.log(obj.arrow());
function Person(name) {
this.name = name;
}
const person1 = new Person("Александр");
const person2 = Person("Мария");
console.log(person1);
console.log(person2);
console.log(window.name); // в браузере
const calculator = {
value: 0,
add: function(num) {
this.value += num;
return this;
},
multiply: (num) => {
this.value *= num;
return this;
}
};
calculator.add(5).multiply(2);
console.log(calculator.value);
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
return count;
},
decrement: () => {
count--;
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // ?
console.log(counter.decrement()); // ?
// Для обычных функций
function calculateSum(a, b) {
return a + b;
}
// Для коротких функций и колбэков
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
// Для методов объектов
const user = {
name: "Александр",
greet() {
return `Привет, ${this.name}!`;
}
};
// Для конструкторов (лучше использовать классы)
class Person {
constructor(name) {
this.name = name;
}
greet() {
return `Привет, я ${this.name}!`;
}
}
// ✅ Хорошо: колбэки и короткие функции
const users = ['Александр', 'Мария', 'Иван'];
const greetings = users.map(name => `Привет, ${name}!`);
// ✅ Хорошо: сохранение контекста this
class Timer {
constructor() {
this.seconds = 0;
}
start() {
setInterval(() => {
this.seconds++; // this указывает на экземпляр Timer
}, 1000);
}
}
// ❌ Плохо: методы объектов
const obj = {
name: "Александр",
greet: () => {
return `Привет, ${this.name}!`; // this не указывает на obj
}
};
// ❌ Плохо: потеря контекста
const person = {
name: "Александр",
greet() {
return `Привет, ${this.name}!`;
}
};
const greetFunc = person.greet;
console.log(greetFunc()); // "Привет, undefined!"
// ✅ Хорошо: привязка контекста
const boundGreet = person.greet.bind(person);
console.log(boundGreet()); // "Привет, Александр!"
// ✅ Или использование стрелочной функции
const arrowGreet = () => person.greet();
console.log(arrowGreet()); // "Привет, Александр!"
this
this
, нельзя использовать как конструкторКлючевые различия:
this
определяет поведение функцииПонимание различий между способами объявления функций — это основа для написания качественного JavaScript кода!
Хочешь больше статей по подготовке к собеседованию? Подпишись на EasyAdvice(@AleksandrEmolov_EasyAdvice), добавляй сайт в избранное и прокачивай себя каждый день 💪