阿里云主机折上折
  • 微信号
Current Site:Index > Function declaration and function expression

Function declaration and function expression

Author:Chuan Chen 阅读数:61785人阅读 分类: JavaScript

In JavaScript, functions can be defined in two primary ways: function declarations and function expressions. These two approaches differ in syntax, hoisting behavior, and execution timing. Understanding these differences is crucial for writing efficient and maintainable code.

Basic Syntax of Function Declarations

A function declaration starts with the function keyword, followed by the function name and a pair of parentheses. The function body is enclosed in curly braces. For example:

function greet(name) {
  return `Hello, ${name}!`;
}

Function declarations are hoisted to the top of their scope, meaning they can be called before they are declared:

console.log(greet('Alice')); // Output: Hello, Alice!

function greet(name) {
  return `Hello, ${name}!`;
}

Basic Syntax of Function Expressions

A function expression assigns a function to a variable or property. It can be anonymous or named:

const greet = function(name) {
  return `Hello, ${name}!`;
};

Unlike function declarations, function expressions are not hoisted. The following code will throw an error:

console.log(greet('Alice')); // TypeError: greet is not a function

const greet = function(name) {
  return `Hello, ${name}!`;
};

Named Function Expressions

Function expressions can include a name, which is useful for debugging:

const factorial = function calcFactorial(n) {
  return n <= 1 ? 1 : n * calcFactorial(n - 1);
};

The name calcFactorial is only visible inside the function and cannot be accessed in the outer scope:

console.log(factorial(5)); // 120
console.log(calcFactorial); // ReferenceError

Arrow Function Expressions

Arrow functions, introduced in ES6, are a concise form of function expressions:

const greet = name => `Hello, ${name}!`;

Arrow functions do not have their own this binding, making them ideal for callbacks:

const obj = {
  values: [1, 2, 3],
  double: function() {
    return this.values.map(v => v * 2); // Correctly inherits 'this'
  }
};

IIFE Pattern

Immediately Invoked Function Expressions (IIFE) can create private scopes:

(function() {
  const privateVar = 'secret';
  console.log(privateVar); // 'secret'
})();

console.log(privateVar); // ReferenceError

Choosing Between Function Declarations and Expressions

Use function declarations when hoisting is needed:

// Allows calling before declaration
setupEventListeners();

function setupEventListeners() {
  // Event handling logic
}

Use function expressions when controlling the timing of function creation:

let logger;

if (debugMode) {
  logger = function(message) {
    console.debug(message);
  };
} else {
  logger = function() {}; // No-op function
}

Passing Functions as Arguments

Function expressions are commonly used in higher-order functions:

const numbers = [1, 2, 3];
const doubled = numbers.map(function(n) {
  return n * 2;
});

Arrow functions make such scenarios more concise:

const tripled = numbers.map(n => n * 3);

Differences in Constructors

Function declarations cannot be directly used as constructors:

function Person(name) {
  this.name = name;
}
const bob = new Person('Bob');

Function expressions assigned to variables can also serve as constructors:

const Animal = function(species) {
  this.species = species;
};
const cat = new Animal('Felis catus');

Comparison in Recursive Implementation

Function declarations are more intuitive for recursive calls:

function fibonacci(n) {
  return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}

Function expressions require ensuring the variable is declared:

const fibonacci = function(n) {
  return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
};

Application in Module Patterns

Function expressions support flexible module definitions:

const counterModule = (function() {
  let count = 0;

  return {
    increment: function() {
      return ++count;
    },
    reset: function() {
      count = 0;
    }
  };
})();

Performance Considerations

Modern JavaScript engines optimize both forms similarly, but function declarations may be slightly faster during parsing due to hoisting:

// Engines prioritize processing function declarations
function heavyComputation() {
  // Complex calculations
}

Debugging Readability

Named functions display more clearly in call stacks:

// Function declaration
function fetchData() {
  throw new Error('Network issue');
}

// Call stack shows 'fetchData'
fetchData();

// Anonymous function expression
const fetchData = function() {
  throw new Error('Network issue');
};

// Call stack shows 'anonymous function'
fetchData();

Dynamic Function Generation

Function expressions allow runtime dynamic creation:

function createMultiplier(factor) {
  return function(x) {
    return x * factor;
  };
}

const double = createMultiplier(2);
console.log(double(5)); // 10

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:严格模式

下一篇:对象枚举与迭代

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.