JavaScript 零基础深入浅出教程:从只会 IF → 高级程序员思维

JavaScript 零基础深入浅出教程:从只会 IF → 高级程序员思维

🎯 学习目标:
不是单纯背语法,建立编程思维。看懂:不同水平的人,同一个需求写出完全不一样的代码;学会权衡【可读性、简洁、性能】,理解底层执行过程。
📌 核心案例贯穿全程:求数组里面所有正数的总和
输入数组:[1, -3, 5, -2, 8, 0],预期结果:14
规则:只把大于0的数字相加,负数、0忽略。

✨ 开篇一句话(给学员)
编程的本质:指挥计算机处理数据。初级程序员只会让计算机重复干活;高级程序员懂得控制循环次数、减少内存浪费,同时代码容易看懂。


第1章:最基础概念(零基础入门)

1.1 变量:存放数据的盒子

// 声明变量,let 代表可变的数据
let num = 10;
let arr = [1, -3, 5, -2, 8, 0]; // 数组:一组数据的集合
let sum = 0; // sum用来保存累加的结果,初始是0
console.log(sum); // 在控制台打印输出

1.2 if 判断:做选择

计算机可以判断条件是否成立,成立就执行代码。

let a = 5;
if(a > 0){
  console.log("a是正数");
}

1.3 数组下标

数组里每一项都有编号(下标,从0开始)

const arr = [1, -3, 5, -2, 8, 0];
console.log(arr[0]); // 1
console.log(arr[1]); // -3
console.log(arr[2]); //5

第2阶段:只会 if 语句(纯新手,不会循环)

思维局限:只能处理固定长度数组,数组元素增减,代码就要增删if。

// 版本1:只会if,硬编码写法
const arr = [1, -3, 5, -2, 8, 0];
let sum = 0;

if(arr[0] > 0){
  sum += arr[0]; // sum = sum + arr[0]
}
if(arr[1] > 0){
  sum += arr[1];
}
if(arr[2] > 0){
  sum += arr[2];
}
if(arr[3] > 0){
  sum += arr[3];
}
if(arr[4] > 0){
  sum += arr[4];
}
if(arr[5] > 0){
  sum += arr[5];
}

console.log(sum); //14

✅ 优点:逻辑直白,只学if就能看懂
❌ 巨大缺点:数组一旦增加元素,就要新增if。数组有1000个元素,要写1000个if!

🧠 思维:只能处理写死的固定场景,没有通用解决问题的能力。


第3阶段:学会 for 循环(入门,学会重复执行)

循环:让计算机自动重复执行一段代码,不用手写一堆if。
i 就是下标,自动从 0,1,2……一直增加到数组末尾。

// 版本2:for循环写法
const arr = [1, -3, 5, -2, 8, 0];
let sum = 0;

// i从0开始;i < arr.length(数组长度);每次循环 i++
for(let i = 0; i < arr.length; i++){
  const item = arr[i]; // 取出当前数组元素
  if(item > 0){
    sum += item;
  }
}
console.log(sum); //14

✅ 优点:任意长度数组都能用,不用改if。只遍历数组1次,不创建新数组,内存开销很小。
❌ 缺点:代码和数据写死在一起。如果想计算另外一个数组正数和,必须复制整段代码。

🧠 思维升级:学会批量处理一组数据,指挥计算机重复劳动。
这种写法叫命令式编程:告诉计算机每一步怎么做。

拓展:for...of 简化循环(不用管下标i)

const arr = [1, -3, 5, -2, 8, 0];
let sum = 0;
for(const item of arr){
  if(item > 0){
    sum += item;
  }
}
console.log(sum);

第4阶段:学会函数封装(中级:学会代码复用)

函数:把一段完成特定功能的代码打包成工具。输入数据,返回结果。
一处定义,到处调用。还可以增加校验,防止错误输入。

// 版本3:函数封装 + for循环
/**
 * 计算数组正数之和
 * @param {Array} list 传入的数组
 * @returns {number} 正数总和
 */
function getPositiveSum(list){
  // 防御校验:如果传入不是数组,直接返回0,避免报错
  if(!Array.isArray(list)) return 0;

  let sum = 0;
  for(let i = 0; i < list.length; i++){
    const item = list[i];
    if(typeof item === "number" && item > 0){
      sum += item;
    }
  }
  return sum;
}

// 调用函数,可以传入不同数组
const arr1 = [1, -3, 5, -2, 8, 0];
const arr2 = [2, -1, 10];
console.log(getPositiveSum(arr1)); //14
console.log(getPositiveSum(arr2)); //12

✅ 优点:代码复用、方便维护,支持多组数据。底层依旧1次遍历,无临时数组。

🧠 思维升级:抽象能力。把“计算正数总和”做成一个工具。


第5阶段:学会数组高阶API filter / reduce(JS进阶:声明式编程)

命令式:告诉计算机怎么做。
声明式:告诉计算机,我想要什么结果。
filter:筛选数组,返回满足条件的新数组
reduce:把数组“压缩”成一个值(总和、对象等)

版本4 filter + reduce(简洁好读)

// 版本4 filter + reduce
function getPositiveSum(list){
  if(!Array.isArray(list)) return 0;
  return list
    .filter(item => typeof item === "number" && item > 0) // 筛选正数,生成新数组
    .reduce((total, item) => total + item, 0); // 累加新数组
}
const arr = [1, -3, 5, -2, 8, 0];
console.log(getPositiveSum(arr)); //14

✅ 优点:代码可读性极高,一眼看懂逻辑:筛选正数,然后求和。
❌ 底层代价(重点!中级学员容易忽略)

  1. 两次遍历:原数组遍历一次生成新数组;新数组再遍历一次求和
  2. filter会创建中间临时数组,占用内存;大数据会增加垃圾回收压力。

适用场景:数组不大(几十几百条数据),可读性优先。


第6阶段:高级程序员写法:兼顾简洁 + 性能(重点章节)

核心思想:减少遍历次数、减少临时内存开销,同时保持代码简洁可读。
✅ 只用 reduce,只遍历数组1次,不生成中间数组。在一轮遍历里面同时完成判断+累加。

/**
 * 【推荐:高级平衡写法】reduce单遍遍历
 * 一次遍历,无中间数组;兼顾简洁性与性能
 * @param {Array} list
 * @returns {number}
 */
function getPositiveSum(list) {
  if (!Array.isArray(list)) return 0;
  return list.reduce((sum, item) => {
    if (typeof item === 'number' && item > 0) {
      sum += item;
    }
    return sum;
  }, 0); // sum初始值=0
}

const arr = [1, -3, 5, -2, 8, 0];
console.log(getPositiveSum(arr)); //14

✅ 底层分析

  • 遍历次数:仅1次
  • 内存:没有创建额外临时数组
    ✅ 优点:
  1. 声明式风格,代码干净,不用手动管理下标i
  2. 性能接近原生for循环,没有额外内存开销

🧠 高级思维:
不要无脑链式调用 filter+map。链式好看,但背后藏着额外遍历、临时数组。
写代码前自问3个问题:

  1. 需要遍历数组多少次?
  2. 是否产生额外临时数组,增加内存压力?
  3. 是否需要中途停止循环?

⚠️ 重要底层知识点(面试必问)

filter map reduce 不能中途break停止遍历! 必须遍历完整个数组。
如果需要找到目标就提前终止循环(例如:总和大于10就停止),只能用 for / for...of:

// for循环可以break提前退出
function getPositiveSumBreak(list) {
  if (!Array.isArray(list)) return 0;
  let sum = 0;
  for (const item of list) {
    if (typeof item === 'number' && item > 0) {
      sum += item;
    }
    if (sum >= 10) {
      break; // 满足条件,直接跳出循环,不再继续遍历
    }
  }
  return sum;
}
console.log(getPositiveSumBreak([1, -3, 5, -2, 8, 0]));

第7章:性能实测(现场演示代码,浏览器控制台直接运行)

console.time 用来计时,对比不同写法耗时,直观感受性能差异。

// 性能测试代码
// 构造超大数组,10万元素
const bigArr = [];
for(let i = 0; i < 100000; i++){
  bigArr.push(Math.random() * 100 - 50); // -50 ~ 50随机数字
}

// 测试 for循环
console.time("for循环");
function sumFor(list){
  let sum =0;
  for(let i=0;i<list.length;i++){
    if(list[i]>0) sum+=list[i];
  }
  return sum;
}
sumFor(bigArr);
console.timeEnd("for循环");

// 测试 reduce单遍
console.time("reduce单遍历");
function sumReduce(list){
  return list.reduce((s,item)=>{
    if(item>0)s+=item;return s;
  },0);
}
sumReduce(bigArr);
console.timeEnd("reduce单遍历");

// 测试 filter + reduce
console.time("filter+reduce");
function sumFilterReduce(list){
  return list.filter(x=>x>0).reduce((s,i)=>s+i,0);
}
sumFilterReduce(bigArr);
console.timeEnd("filter+reduce");

运行现象:大数据下 filter+reduce 耗时更高,因为两次遍历+创建临时数组。
💡 结论:小数据看不出差别;大数据,开销才会显现。不要过早优化!优先可读性,只在性能瓶颈处优化。


全版本对比总表(上课总结)

版本 知识点 遍历次数 临时数组 思维层次 适用场景
1 if硬编码 0(手动写死) 无 新手 固定少量数据,无法通用
2 for循环 1次 无 入门 大数据,需要break提前退出
3 函数封装+for 1次 无 中级 代码复用,业务基础开发
4 filter+reduce 2次 有 进阶 小数据,追求可读性
5 reduce单遍历 1次 无 高级 绝大多数业务,可读性+性能平衡点

📖 核心学习总结(给学员背诵)

  1. 初级:只会写if硬编码;只能处理固定数据。
  2. 入门:学会循环,让计算机重复干活。
  3. 中级:学会函数封装,代码复用。
  4. 进阶:掌握数组高阶API,写出简洁声明式代码,但忽略底层开销。
  5. 高级:写出代码时,心里清楚遍历次数、内存开销。懂得权衡可读性和性能。

💡 终极口诀
小数据,可读性优先;大数据,减少遍历与临时变量;需要提前终止,就用for循环。

✍️ 课后练习

需求:给定数组,计算数组所有偶数总和

  1. for循环版本
  2. filter + reduce版本,并分析遍历次数和临时数组
  3. reduce单遍历版本

如果你需要,我可以:

  1. 精简成一页讲义;
  2. 或者配套课后答案解析。

要不要我把课后练习题加上完整参考答案?

posted @ 2026-10-15 17:21  华腾智算  阅读(6)  评论(0)    收藏  举报
https://damo.alibaba.com/ https://tianchi.aliyun.com/course?spm=5176.21206777.J_3941670930.5.87dc17c9BZNvLL