指南

深入理解 JavaScript 函数

详细剖析 JavaScript 函数的用法、原理与细节,帮助前端小白真正理解函数的本质。

🎯 引言

你将全面掌握 JavaScript 函数的各种用法,理解函数的创建、调用及执行过程,搞明白函数作用域、闭包和参数传递等重要知识点。掌握这些内容后,你能写出更简洁、高效的代码,避免常见陷阱,提升前端开发能力。


🔍 函数是什么?从零开始理解

JS 函数,本质上是一段可重复执行的代码块。它帮我们把复杂的任务拆分成小块,方便调用和管理。就像厨房里的厨师,函数是完成某道菜的步骤,厨师按照步骤来做菜,函数就按代码执行任务。

常见的创建函数方式有三种:

// 函数声明
function greet(name) {
    return '你好,' + name + '';
}

// 函数表达式
const greet2 = function (name) {
    return '你好,' + name + '';
};

// 箭头函数(ES6,不在本篇重点)
const greet3 = name => '你好,' + name + '';
初学者建议重点掌握函数声明和函数表达式,箭头函数先放一放,后续深入学习。

🧩 函数的调用和返回

调用函数就是让它执行里面的代码,比如:

console.log(greet('小明'));

这句代码会输出“你好,小明!”。函数执行完后,遇到 return 会把结果返回给调用者。如果没有返回值,默认返回 undefined

函数也可以不带参数,比如:

function sayHi() {
    console.log('嗨!');
}
sayHi();

🧠 作用域与函数作用域

作用域决定了变量在哪里有效。JavaScript 函数自带“作用域”,函数内部定义的变量外面访问不到。

function foo() {
    let message = 'Hello';
    console.log(message);
}
foo();
console.log(message); // 报错,message 未定义

函数执行时,会形成一个独立的作用域,里面的变量不会影响外面,外面也访问不到函数内部变量。

理解函数作用域对避免变量冲突非常重要,尤其是在大型项目里。

🔄 参数与实参:传值还是传引用?

JS 函数传递参数时,有两个重要概念:

  • 基本类型参数(比如数字、字符串、布尔)是传值的,函数内修改不会影响外面变量。
  • 引用类型参数(比如对象、数组)是传引用的,函数内修改会影响外部。

举个例子:

function changeNumber(num) {
    num = 100;
}
let a = 50;
changeNumber(a);
console.log(a); // 50,外部没变

function changeObj(obj) {
    obj.name = '小明';
}
let person = { name: '小红' };
changeObj(person);
console.log(person.name); // 小明

🔒 闭包:函数的神奇力量

闭包是 JS 函数最强大的特点之一。简单来说,函数可以“记住”创建它时外部的变量,即使外部函数已经执行完。

function outer() {
    let count = 0;
    return function inner() {
        count++;
        console.log('计数器:', count);
    };
}

const counter = outer();
counter(); // 计数器:1
counter(); // 计数器:2

这里 inner 函数访问了 outer 函数的变量 count,并且 count 信息被保留下来,形成闭包。

闭包非常适合做计数器、缓存数据这样的场景。


📝 函数声明 vs 函数表达式

两者看起来很像,但有个重要区别是“提升”(hoisting)。

函数声明会被 JS 解析器提前加载,你可以在声明之前调用。

sayHello();

function sayHello() {
    console.log('Hello');
}

函数表达式则不会提升,必须先定义再调用,否则报错。

sayHi(); // 报错

const sayHi = function () {
    console.log('Hi');
};

💡 小提示:函数默认参数模拟

在 JavaScript 中,如果函数调用时没有传入某个参数,它的值会是 undefined。可以通过在函数内部手动检查参数是否传入,并设置默认值:

function greet(name) {
    if (typeof name === 'undefined') {
        name = '朋友';
    }
    return '你好,' + name + '';
}

🧾 小节总结

  • JS 函数是封装可复用代码的基本单位,理解函数声明、调用、参数传递很关键。
  • 函数作用域保护变量,闭包让函数“记住”外部变量,是解决复杂业务的利器。
  • 注意函数声明和函数表达式的提升差异,合理利用默认参数和闭包提高代码质量。

❓ 知识问答(Q&A)

Q:函数表达式和函数声明有什么区别?
A:函数声明会被提升,可以先调用后声明;函数表达式不会提升,必须先定义后调用。

Q:闭包是什么,有什么作用?
A:闭包是函数“记住”定义时的外部变量。它能让函数访问并操作外部函数的局部变量,常用于数据缓存和私有变量。


🧪 小练习

练习1:写一个函数,接收两个参数,返回它们的乘积。调用这个函数并打印结果。

function multiply(a, b) {
    // 实现代码
}

console.log(multiply(3, 5)); // 期望输出 15

练习2:利用闭包写一个计数器函数,调用它每次数字加 1,并返回当前计数。

function createCounter() {
    // 返回一个内部函数,实现计数功能
}

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2

🎉 恭喜你已经掌握 JS 函数的声明、调用、作用域、参数传递和闭包等核心技能啦!祝你前端学习之路顺利!