程序猿前端之JavaScript - Day03 - for语句与数组应用实战

JavaScript 基础第三天笔记

if 多分支语句和 switch的区别:

  1. 共同点

    • 都能实现多分支选择, 多选1

    • 大部分情况下可以互换

  2. 区别:

    • switch…case语句通常处理case为比较确定值的情况,而if…else…语句更加灵活,通常用于范围判断(大于,等于某个范围)。

    • switch 语句进行判断后直接执行到程序的语句,效率更高,而if…else语句有几种判断条件,就得判断多少次

    • switch 一定要注意 必须是 === 全等,一定注意 数据类型,同时注意break否则会有穿透效果

    • 结论:

      • 当分支比较少时,if…else语句执行效率高。

      • 当分支比较多时,switch语句执行效率高,而且结构更清晰。

for 语句

掌握 for 循环语句,让程序具备重复执行能力

for 是 JavaScript 提供的另一种循环控制的话句,它和 while 只是语法上存在差异。

for语句的基本使用

  1. 实现循环的 3 要素

<script>
  // 1. 语法格式
  // for(起始值; 终止条件; 变化量) {
  //   // 要重复执行的代码
  // }
​
  // 2. 示例:在网页中输入标题标签
  // 起始值为 1
  // 变化量 i++
  // 终止条件 i <= 6
  for(let i = 1; i <= 6; i++) {
    document.write(`<h${i}>循环控制,即重复执行<h${i}>`)
  }
</script>
  1. 变化量和死循环,for 循环和 while 一样,如果不合理设置增量和终止条件,便会产生死循环。

  1. 跳出和终止循环

<script>
    // 1. continue 
    for (let i = 1; i <= 5; i++) {
        if (i === 3) {
            continue  // 结束本次循环,继续下一次循环
        }
        console.log(i)
    }
    // 2. break
    for (let i = 1; i <= 5; i++) {
        if (i === 3) {
            break  // 退出结束整个循环
        }
        console.log(i)
    }
</script>

结论:

  • JavaScript 提供了多种语句来实现循环控制,但无论使用哪种语句都离不开循环的3个特征,即起始值、变化量、终止条件,做为初学者应着重体会这3个特征,不必过多纠结三种语句的区别。

  • 起始值、变化量、终止条件,由开发者根据逻辑需要进行设计,规避死循环的发生。

  • 当如果明确了循环的次数的时候推荐使用for循环,当不明确循环的次数的时候推荐使用while循环

注意:for 的语法结构更简洁,故 for 循环的使用频次会更多。

循环嵌套

利用循环的知识来对比一个简单的天文知识,我们知道地球在自转的同时也在围绕太阳公转,如果把自转和公转都看成是循环的话,就相当于是循环中又嵌套了另一个循环。

 

实际上 JavaScript 中任何一种循环语句都支持循环的嵌套,如下代码所示:

 

// 1. 外面的循环 记录第n天 
for (let i = 1; i < 4; i++) {
    document.write(`第${i}天 <br>`)
    // 2. 里层的循环记录 几个单词
    for (let j = 1; j < 6; j++) {
        document.write(`记住第${j}个单词<br>`)
    }
}

记住,外层循环循环一次,里层循环循环全部

倒三角
 // 外层打印几行
for (let i = 1; i <= 5; i++) {
    // 里层打印几个星星
    for (let j = 1; j <= i; j++) {
        document.write('★')
    }
    document.write('<br>')
}

 

九九乘法表

样式css

span {
    display: inline-block;
    width: 100px;
    padding: 5px 10px;
    border: 1px solid pink;
    margin: 2px;
    border-radius: 5px;
    box-shadow: 2px 2px 2px rgba(255, 192, 203, .4);
    background-color: rgba(255, 192, 203, .1);
    text-align: center;
    color: hotpink;
}

javascript

 // 外层打印几行
for (let i = 1; i <= 9; i++) {
    // 里层打印几个星星
    for (let j = 1; j <= i; j++) {
        // 只需要吧 ★ 换成  1 x 1 = 1   
        document.write(`
        <div> ${j} x ${i} = ${j * i} </div>
     `)
    }
    document.write('<br>')
}

 

数组

知道什么是数组及其应用的场景,掌握数组声明及访问的语法。

数组是什么?

数组:(Array)是一种可以按顺序保存数据的数据类型

使用场景:如果有多个数据可以用数组保存起来,然后放到一个变量中,管理非常方便

数组的基本使用

定义数组和数组单元
<script>
  // 1. 语法,使用 [] 来定义一个空数组
  // 定义一个空数组,然后赋值给变量 classes
  // let classes = [];
​
  // 2. 定义非空数组
  let classes = ['小明', '小刚', '小红', '小丽', '小米']
</script>

通过 [] 定义数组,数据中可以存放真正的数据,如小明、小刚、小红等这些都是数组中的数据,我们这些数据称为数组单元,数组单元之间使用英文逗号分隔。

访问数组和数组索引

使用数组存放数据并不是最终目的,关键是能够随时的访问到数组中的数据(单元)。其实 JavaScript 为数组中的每一个数据单元都编了号,通过数据单元在数组中的编号便可以轻松访问到数组中的数据单元了。

我们将数据单元在数组中的编号称为索引值,也有人称其为下标。

索引值实际是按着数据单元在数组中的位置依次排列的,注意是从0 开始的,如下图所示:

 

观察上图可以数据单元【小明】对应的索引值为【0】,数据单元【小红】对应的索引值为【2】

<script>
  let classes = ['小明', '小刚', '小红', '小丽', '小米']
  
  // 1. 访问数组,语法格式为:变量名[索引值]
  document.write(classes[0]) // 结果为:小明
  document.write(classes[1]) // 结果为:小刚
  document.write(classes[4]) // 结果为:小米
  
  // 2. 通过索引值还可以为数组单重新赋值
  document.write(classes[3]) // 结果为:小丽
  // 重新为索引值为 3 的单元赋值
  classes[3] = '小小丽'
  document.wirte(classes[3]); // 结果为: 小小丽
</script>
数据单元值类型

数组做为数据的集合,它的单元值可以是任意数据类型

<script>
  // 6. 数组单值类型可以是任意数据类型
​
  // a) 数组单元值的类型为字符类型
  let list = ['HTML', 'CSS', 'JavaScript']
  // b) 数组单元值的类型为数值类型
  let scores = [78, 84, 70, 62, 75]
  // c) 混合多种类型
  let mixin = [true, 1, false, 'hello']
</script>
数组长度属性

重申一次,数组在 JavaScript 中并不是新的数据类型,它属于对象类型。

<script>
  // 定义一个数组
  let arr = ['html', 'css', 'javascript']
  // 数组对应着一个 length 属性,它的含义是获取数组的长度
  console.log(arr.length) // 3
</script>

操作数组

数组做为对象数据类型,不但有 length 属性可以使用,还提供了许多方法:

  1. push 动态向数组的尾部添加一个单元

  2. unshit 动态向数组头部添加一个单元

  3. pop 删除最后一个单元

  4. shift 删除第一个单元

  5. splice 动态删除任意单元

使用以上4个方法时,都是直接在原数组上进行操作,即成功调任何一个方法,原数组都跟着发生相应的改变。并且在添加或删除单元时 length 并不会发生错乱。

<script>
  // 定义一个数组
  let arr = ['html', 'css', 'javascript']
​
  // 1. push 动态向数组的尾部添加一个单元
  arr.push('Nodejs')
  console.log(arr)
  arr.push('Vue')
​
  // 2. unshit 动态向数组头部添加一个单元
  arr.unshift('VS Code')
  console.log(arr)
​
  // 3. splice 动态删除任意单元
  arr.splice(2, 1) // 从索引值为2的位置开始删除1个单元
  console.log(arr)
​
  // 4. pop 删除最后一个单元
  arr.pop()
  console.log(arr)
​
  // 5. shift 删除第一个单元
  arr.shift()
  console.log(arr)
</script>

理解

一、理论理解

for 语句本质

for 语句是 JavaScript 中最经典的循环控制语法,它比 while 更紧凑,适用于已知次数的循环场景。

基本结构:

for (初始值; 终止条件; 变量变化) {
  // 循环体
}

其核心组成正好符合“循环三要素”:起始条件 + 终止判断 + 状态推进

通过 breakcontinue 可精细控制循环行为:

  • break:退出整个循环体;

  • continue:跳过本次循环,继续下一轮。

此外,循环嵌套九九乘法表的实现,强调了多层次逻辑与排列组合思想,在数据展示、表格生成等场景中极为常见。


✅ 数组本质

数组是 JS 中用于组织一组有序数据的对象结构:

let arr = ['小明', '小红'];
  • 数组的数据项通过索引值访问,索引从 0 开始;

  • 支持动态读写、替换和扩展;

  • 所有数组都有 .length 属性,可以获取当前数组的元素个数;

  • 是 JS 中最常见的数据容器之一。

数组支持五大基础操作:

  • push():尾部添加;

  • unshift():头部添加;

  • splice():任意位置添加/删除;

  • pop():尾部删除;

  • shift():头部删除。


二、大厂实战理解

✅ 字节跳动:for循环+嵌套实现业务结构化渲染

在字节跳动的抖音 Web 页面中,常常需要用 for 嵌套循环结构动态渲染 DOM 元素,例如:

for (let section of homepageSections) {
  for (let item of section.items) {
    renderComponent(item);
  }
}

页面模块即为二维数据渲染结构,核心就是“循环嵌套+条件逻辑”的组合。


✅ 阿里巴巴:数组作为动态数据模型核心

阿里后台管理系统(如运营中台)中,大量配置项是通过数组组织并绑定页面数据模型的:

formFields = [
  { label: '用户名', value: '', type: 'text' },
  { label: '密码', value: '', type: 'password' },
];
  • 数据驱动视图;

  • 通过 .push() 动态插入;

  • 通过 .splice() 删除配置项;

  • 配合 forEachmap 等方法实现遍历渲染。


✅ Google:V8 对 for-loop 优化明显

Google 在 V8 引擎中针对 for 结构的性能优化极深:

  • JIT 编译器识别“静态循环”(起始+结束条件固定)时会进行内联优化;

  • while 更能被引擎优化为高效底层循环。

因此,大厂代码规范经常建议优先使用 for 而非 while


✅ OpenAI:数组为对话状态主容器

OpenAI 的 Chat 模型会使用数组结构维护历史会话内容:

[
  { role: 'user', content: '你好' },
  { role: 'assistant', content: '你好,有什么可以帮您?' }
]

每次新的用户请求通过 push() 添加到消息数组中,再送入模型进行上下文推理。这正是前端数组应用在 AI 系统中的典型实践。


✅ NVIDIA:图形引擎中嵌套循环控制图层渲染

在 NVIDIA 的图形渲染框架中,嵌套循环控制多个图层、多个对象的绘制顺序:

for (let layer of renderLayers) {
  for (let object of layer.objects) {
    object.draw();
  }
}

性能关键路径中,这种嵌套循环需要极致优化,甚至编译为 GLSL 着色器中的循环指令。


大厂面试题


❓1. [字节跳动一面] 如何用 for 循环从数组中找出所有偶数?请写出完整代码。

参考答案:

let arr = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < arr.length; i++) {
  if (arr[i] % 2 === 0) {
    console.log(arr[i]);
  }
}

❓2. [阿里二面] JavaScript 中数组索引从 0 开始的原因是什么?

解析:

  • 来自 C 语言的设计哲学;

  • 计算偏移量更高效(arr[i] = base_address + i * size);

  • 现代内存模型中,从 0 开始是访问第一个元素的自然写法;

  • 更符合位运算等底层优化策略。


❓3. [腾讯 T4 面试] 用 splice() 实现:从数组中删除所有值为 0 的元素。

参考答案:

let arr = [1, 0, 2, 0, 3];
for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 0) {
    arr.splice(i, 1);
    i--; // 注意索引回退,否则跳过下一个元素
  }
}
console.log(arr); // [1, 2, 3]

❓4. [百度前端笔试题] forEachmapfor 有什么区别?哪个更适合性能敏感场景?

对比:

方法能中断是否返回新数组性能适用场景
for性能最好性能敏感或可控流程
forEach中等遍历执行副作用逻辑
map中等偏高映射转换生成新数组

❓5. [Google Web Engineer 面试题] 写出一个嵌套 for 循环,用于输出 3 天内每天背 5 个单词的学习记录(控制台输出)。

参考答案:

for (let day = 1; day <= 3; day++) {
  console.log(`第 ${day} 天`);
  for (let word = 1; word <= 5; word++) {
    console.log(`背第 ${word} 个单词`);
  }
}

❓6. [小米一面] 用一行代码实现数组反转(不使用 reverse() 方法)。

参考答案:

let arr = [1, 2, 3];
let reversed = arr.map((_, i, a) => a[a.length - 1 - i]);
console.log(reversed); // [3, 2, 1]

大厂场景题


💼 场景 1:[字节跳动 · 电商前台商品瀑布流展示]

**背景:**商品页加载后,后端返回多组商品数据(二维数组),页面需逐行渲染商品卡片,每行最多渲染 4 个商品。

**任务:**请用嵌套 for 循环遍历数据并输出商品信息:

const goodsList = [
  ['手机', '耳机', '手表', '平板'],
  ['外套', 'T恤', '牛仔裤'],
  ['牙刷', '牙膏', '洗面奶', '沐浴露', '毛巾']
];

for (let i = 0; i < goodsList.length; i++) {
  console.log(`第${i + 1}行商品:`);
  for (let j = 0; j < goodsList[i].length; j++) {
    console.log(` - ${goodsList[i][j]}`);
  }
}

💼 场景 2:[阿里巴巴 · 菜单动态渲染系统]

**背景:**后端返回的菜单结构为一维数组,开发者需使用数组与 DOM 循环动态绑定生成侧边栏菜单。

**任务:**将以下菜单数组渲染为 <ul><li>...</li></ul> 结构:

const menus = ['首页', '商品管理', '订单管理', '用户管理'];

document.write('<ul>');
for (let i = 0; i < menus.length; i++) {
  document.write(`<li>${menus[i]}</li>`);
}
document.write('</ul>');

💼 场景 3:[腾讯 · 微信群聊成员渲染]

**背景:**微信前端需从成员数组中生成每个成员卡片,每 5 个换一行排布。

**任务:**使用 for 循环实现换行逻辑:

const users = ['张三', '李四', '王五', '赵六', '田七', '钱八', '孙九', '周十'];

for (let i = 0; i < users.length; i++) {
  document.write(`<span>${users[i]}</span>`);
  if ((i + 1) % 5 === 0) {
    document.write('<br>');
  }
}

💼 场景 4:[Google Docs · 操作历史记录列表]

**背景:**Google 文档前端维护一个操作历史列表,每次操作会追加到数组中,最多显示 10 条,超过则删除最早一条。

**任务:**模拟用户操作过程,使用数组方法实现追加与限制:

let history = [];

function addAction(action) {
  history.push(action);
  if (history.length > 10) {
    history.shift(); // 删除最前面一项
  }
  console.log(history);
}

addAction('输入文字');
addAction('加粗文字');
addAction('插入图片');
// ...

💼 场景 5:[OpenAI · 聊天消息记录管理]

**背景:**OpenAI 聊天系统前端维护一个用户消息数组,每次发送新消息添加到尾部,用户还可以删除最后一条消息(撤回)。

**任务:**用数组方法实现:

let messages = [];

function sendMessage(content) {
  messages.push(content);
  console.log('发送:', messages);
}

function undoLastMessage() {
  messages.pop();
  console.log('撤回:', messages);
}

sendMessage('你好');
sendMessage('今天天气不错');
undoLastMessage();

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏驰和徐策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值