Skip to content

JavaScript 函数

核心基础 JavaScript Functions

一、为什么需要函数

1.1 问题:代码重复

想象一个 家务机器人,每天需要执行买牛奶的流程:

javascript
alert("leaveHouse");
alert("moveRight");
alert("moveRight");
alert("moveUp");
alert("moveUp");
alert("moveUp");
alert("moveUp");
alert("buyMilk");
alert("moveDown");
// ... 还有更多

如果每天都要重新写一遍,效率极低。

1.2 解决方案:封装为函数

把一系列指令 打包 成一个可复用的代码块:

javascript
function getMilk() {
  console.log("leaveHouse");
  console.log("moveRight");
  console.log("moveRight");
  console.log("buyMilk");
  console.log("moveLeft");
  console.log("moveLeft");
  console.log("enterHouse");
}

getMilk();  // 一行代码执行所有步骤
getMilk();  // 可以重复调用

二、函数的三种形态 🍦

就像经典 Neapolitan 冰淇淋有三种口味,函数也有三种形态:

2.1 🍦 Vanilla — 基本函数(无输入无输出)

最简单的函数,只包装一组固定指令。

javascript
// 创建函数
function getMilk() {
  console.log("Go to store");
  console.log("Buy milk");
  console.log("Come back");
}

// 调用函数
getMilk();

语法结构:

组成部分作用
function关键字,声明要创建函数
getMilk函数名(遵循驼峰命名)
()圆括号(此处为空,无参数)
{...}花括号,包裹函数体

创建 vs 调用

  • 创建:需要 function 关键字 + 花括号
  • 调用:只写函数名 + 圆括号 + 分号:getMilk();

2.2 🍫 Chocolate — 带参数的函数(有输入)

函数可以接收 输入(参数),并在内部使用:

javascript
function getMilk(bottles) {
  var cost = bottles * 1.5;
  console.log("Buy " + bottles + " bottles of milk");
  console.log("Total cost: $" + cost);
}

getMilk(2);   // bottles = 2, cost = $3.0
getMilk(5);   // bottles = 5, cost = $7.5

术语区分:

术语位置示例
参数 (Parameter)函数定义中function getMilk(bottles) 中的 bottles
实参 (Argument)函数调用时getMilk(2) 中的 2

2.3 多参数

函数可以接收 多个参数,用逗号分隔:

javascript
function getMilk(money, costPerBottle) {
  var numberOfBottles = Math.floor(money / costPerBottle);
  console.log("Buy " + numberOfBottles + " bottles of milk");
}

getMilk(10, 1.5);  // 可以买 6 瓶
getMilk(5, 2.0);   // 可以买 2 瓶

2.4 🍓 Strawberry — 带返回值的函数(有输入有输出)

使用 return 关键字让函数 输出 一个值:

javascript
function getMilk(money) {
  var numberOfBottles = Math.floor(money / 1.5);
  console.log("Buy " + numberOfBottles + " bottles");
  return money % 1.5;  // 返回找零
}

var change = getMilk(4);
console.log("Change: $" + change);  // Change: $1

工作流程:

  1. 调用 getMilk(4)money = 4
  2. 计算 numberOfBottles = Math.floor(4 / 1.5)2
  3. return 4 % 1.5 → 输出 1
  4. change = 1

return 的作用

return 让函数的调用表达式 变成一个值,可以被赋给变量、传入其他函数或参与运算。


三、函数嵌套与模块化

3.1 函数调用函数

可以在一个函数内 调用 另一个函数,实现模块化:

javascript
function calcBottles(startingMoney, costPerBottle) {
  var numberOfBottles = Math.floor(startingMoney / costPerBottle);
  return numberOfBottles;
}

function calcChange(startingAmount, costPerBottle) {
  var change = startingAmount % costPerBottle;
  return change;
}

function getMilk(money, costPerBottle) {
  console.log("Buy " + calcBottles(money, costPerBottle) + " bottles");
  return calcChange(money, costPerBottle);
}

var change = getMilk(10, 1.5);
console.log("Here is your $" + change + " change.");

3.2 模块化的好处

  • 可复用calcBottles() 可以在任何需要计算数量的地方使用
  • 易维护:如果计算逻辑变了,只需修改一处
  • 易调试:可以单独测试每个小函数

四、console.log vs alert

特性alert()console.log()
可见对象用户(网站访客)开发者
呈现方式弹窗对话框控制台文本
使用场景需要用户交互调试、测试、日志
阻断性阻断执行,需点击 OK不阻断
javascript
// 用户可见
alert("Welcome!");

// 仅开发者可见(F12 → Console)
console.log("Debug: user logged in");

五、Karel 机器人练习

Karel the Robot 是 Stanford 的教学工具,用于练习 函数抽象 思维。

5.1 基本命令

命令功能
move()向前移动一格
turnLeft()左转 90°
putBeeper()放下标记
pickBeeper()捡起标记

5.2 函数抽象示例

javascript
// 将重复动作封装为函数
function moveFourTimes() {
  move();
  move();
  move();
  move();
}

// 主程序变得简洁
function main() {
  moveFourTimes();
  turnLeft();
  moveFourTimes();
}

5.3 对角线放置标记

javascript
function diagonalMoveAndBeeper() {
  move();
  turnLeft();
  move();
  putBeeper();
  turnRight();
}

function main() {
  putBeeper();
  diagonalMoveAndBeeper();
  diagonalMoveAndBeeper();
  diagonalMoveAndBeeper();
  diagonalMoveAndBeeper();
}

六、实战练习

6.1 BMI 计算器

javascript
function bmiCalculator(weight, height) {
  var bmi = weight / Math.pow(height, 2);
  return Math.round(bmi);
}

var bmi = bmiCalculator(65, 1.8);
console.log("Your BMI is: " + bmi);  // 20

6.2 Life in Weeks

javascript
function lifeInWeeks(age) {
  var yearsRemaining = 90 - age;
  var days = yearsRemaining * 365;
  var weeks = yearsRemaining * 52;
  var months = yearsRemaining * 12;
  console.log("You have " + days + " days, " +
              weeks + " weeks, and " +
              months + " months left.");
}

lifeInWeeks(25);

七、Angela 的建议:正确设定预期

关于编程难度的真相

  • ❌ "编程很简单,人人都能学" — 这是不负责任的说法
  • ❌ "编程只有天才才能学" — 这也不对
  • 编程是困难的,但通过持续努力是完全可以掌握的

没有人天生就是程序员。区别只在于 投入的练习量


← 返回 Web 开发研究