基础 | 🔥6种声明方式全解⚠️

一、ES6 的6种变量声明方式(含实战陷阱与追问链)

ES6(ECMAScript 2015)带来了语言层面的巨大升级,其中变量声明机制 是开发者最直观感受到的变革。它不再局限于 var,而是引入了更安全、更语义化的多种声明方式。

我们先看一张核心对比图:

graph LR A[变量声明] --> B[var] A --> C[let] A --> D[const] A --> E[function] A --> F[class] A --> G[import] style B fill:#f96,stroke:#333 style C fill:#6f9,stroke:#333 style D fill:#69f,stroke:#333 style E fill:#ff6,stroke:#333 style F fill:#6ff,stroke:#333 style G fill:#f6f,stroke:#333

⚡图:ES6 六大声明方式全景图

⚠️这一步暗藏变量提升陷阱?

1. var ------ 被时代淘汰但仍在运行时存在

  • 函数作用域
  • 存在变量提升(hoisting)
  • 可重复声明
  • 不推荐在现代项目中使用
js 复制代码
console.log(a); // undefined(不是报错!)
var a = 1;

2. let ------ 块级作用域新标准

  • 块级作用域({} 内有效)
  • 不存在"暂时性死区"外的访问
  • 不可重复声明
  • 推荐用于可变变量
js 复制代码
{
  let b = 2;
  console.log(b); // 2
}
console.log(b); // ReferenceError!

3. const ------ 常量声明(但≠不可变!)

  • 块级作用域
  • 必须初始化
  • 引用地址不可变,但对象属性可改
js 复制代码
const obj = { name: 'ES6' };
obj.name = 'Modern JS'; // ✅ 合法
obj = {}; // ❌ 报错:Assignment to constant variable.

4. function ------ 函数声明(也是ES6前就有的)

  • 提升且初始化
  • 仅在定义的作用域内有效
  • let/const 冲突时会抛错
js 复制代码
function foo() { return 1; }

5. class ------ 语法糖,本质仍是函数

  • 必须先定义后使用(TDZ)
  • 不会被提升
  • class 声明创建一个不可重新赋值的常量
js 复制代码
class Person {
  constructor(name) {
    this.name = name;
  }
}
const p = new Person('Tom');

6. import ------ 模块导入即声明

  • 静态分析,编译时绑定
  • 所有 import 自动提升到文件顶部
  • 绑定是只读引用,不是拷贝
js 复制代码
import { useState } from 'react'; // 声明了一个只读绑定

📌 主流共识:letconst 是现代 JS 开发的默认选择,优先使用 const,仅当需要重新赋值时用 let


「Q1: varlet 最大区别是什么?💥」

A1: var 是函数作用域且会变量提升并初始化为 undefinedlet 是块级作用域,存在暂时性死区(TDZ),在声明前访问会报错。

「Q2: const 定义的对象为什么还能修改属性?🤯」

A2: const 保证的是引用地址不变 ,而非对象内部不可变。要真正冻结对象需用 Object.freeze(obj)

「Q3: import 是不是也受 TDZ 影响?」

A3: 是的!虽然 import 会被提升,但在模块执行前无法访问,属于 TDZ 范畴。比如动态 import() 可以规避。

「Q4: class 声明会不会被提升?」

A4: class 声明存在 TDZ,不会被提升。typeof MyClass 在声明前会报错,不像 function 可以提前使用。

「Q5: 为什么 ES6 不直接废弃 var?」

A5: 为了向后兼容。大量旧代码依赖 var 行为,直接移除会导致生态崩溃。但规范鼓励使用 let/const


二、CSS 元素垂直居中的 7 种方式

垂直居中是前端永恒话题。我们先上一张布局方式演进图:

sql 复制代码
+------------------+     +------------------+
|   display:table  |     | position + 负margin |
+------------------+     +------------------+
          |                        |
          v                        v
+------------------+     +------------------+
|  flex: center!!  |<--->|    grid layout   |
+------------------+     +------------------+
          |
          v
+------------------+
| transform:translate(-50%) |
+------------------+

⚡图:CSS 垂直居中方法演进路径

⚠️移动端慎用负 margin?

方法 1:Flexbox(推荐 ✅)

css 复制代码
.container {
  display: flex;
  justify-content: center; /* 水平 */
  align-items: center;     /* 垂直 */
  height: 100vh;
}

方法 2:Grid(现代方案)

css 复制代码
.container {
  display: grid;
  place-items: center; /* 水平+垂直 */
  height: 100vh;
}

方法 3:绝对定位 + transform

css 复制代码
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

方法 4:绝对定位 + margin auto

css 复制代码
.container {
  position: relative;
  height: 300px;
}
.child {
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  margin: auto;
  width: 100px;
  height: 50px;
}

方法 5:table-cell(老派但兼容好)

css 复制代码
.container {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  width: 300px;
  height: 300px;
}

方法 6:line-height(仅限单行文本)

css 复制代码
.box {
  height: 100px;
  line-height: 100px;
  text-align: center;
}

方法 7:padding 调整(固定高度可用)

css 复制代码
.box {
  padding: 50px 0;
  height: 200px;
  box-sizing: border-box;
}

「Q1: Flex 居中会不会影响子元素布局?💥」

A1: 不会,align-itemsjustify-content 只控制主轴和交叉轴对齐,子元素仍可自由布局。

「Q2: transform: translate 会导致模糊?🤯」

A2: 是的!非整数像素位移可能引起亚像素渲染模糊。可加 will-change: transform 或强制 GPU 加速缓解。

「Q3: Grid 和 Flex 如何选?」

A3: Grid 适合二维布局(行列都复杂),Flex 适合一维(主轴方向)。居中场景两者皆可,优先 Flex。

「Q4: 为什么不用 vertical-align: middle?」

A4: 因为它只对 inlinetable-cell 元素有效,块级元素无效,常被误解。

「Q5: 移动端适配居中要注意什么?🌍」

A5: 避免固定高度,优先使用 Flex 或 Grid,结合 vh 单位,并处理 iOS 安全区(env() 函数)。


三、Flex 布局的三大伸缩属性详解(含权重计算)

Flex 布局核心在于三个伸缩属性:

classDiagram class FlexItem { +flex-grow: number +flex-shrink: number +flex-basis: length | auto } FlexItem : flex = grow shrink basis

⚡图:Flex 伸缩三属性关系

⚠️默认值组合有坑?

1. flex-grow:剩余空间分配权重

  • 默认 0
  • 数值越大,分得越多
  • 不会缩小已有内容
css 复制代码
.item1 { flex-grow: 1; }
.item2 { flex-grow: 2; } /* 分得两倍空间 */

2. flex-shrink:溢出时压缩比例

  • 默认 1
  • 设为 0 表示不压缩
  • 压缩量 = (自身大小 × shrink) / 总权重
css 复制代码
.item { flex-shrink: 0; } /* 固定宽度,不压缩 */

3. flex-basis:分配前的初始大小

  • 类似 width,但优先级更高
  • 可设为 auto(按内容)、0、具体值
css 复制代码
.item { flex-basis: 100px; }

简写 flex 的常见组合:

写法 等价于
flex: 1 1 1 0%1 1 0px(浏览器差异)
flex: auto 1 1 auto
flex: none 0 0 auto(不伸不缩)

💡 实战建议:用 flex: 1 快速填满剩余空间,flex: none 防止压缩。

「Q1: flex: 1 到底等于 1 1 0 还是 1 1 auto?💥」

A1: 规范定义为 1 1 0,但某些浏览器实现为 0%。为明确行为,建议写全。

「Q2: flex-basis: 0width: 0 一样吗?🤯」

A2: 不同!flex-basis 参与 flex 计算,width 在 flex 中可能被覆盖。flex-basis: 0 更适合均分。

「Q3: 多个 item 设置 flex-grow 如何计算?」

A3: 按权重比例分配剩余空间。如 grow=1 和 grow=2,则比例 1:2。

「Q4: flex-shrink 为负数会怎样?」

A4: 无效!flex-shrink 必须是非负数,负值会被忽略或转为 0。

「Q5: 为什么有时 flex: 1 不占满?」

A5: 可能父容器无固定宽度,或子元素有 min-width 限制。检查 min-width: auto 是否干扰。


四、LeetCode 开平方根题(第69题)------ 二分法 vs 牛顿法

题目:实现 int sqrt(int x),返回 √x 的整数部分。

例:输入 8 → 输出 2(√8 ≈ 2.828)

方法 1:二分查找(推荐 ✅)

js 复制代码
function mySqrt(x) {
  if (x < 2) return x;
  let left = 1, right = Math.floor(x / 2);
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    const square = mid * mid;
    if (square === x) return mid;
    if (square < x) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return right; // 最大满足 mid*mid <= x 的值
}

方法 2:牛顿迭代法(更快收敛)

js 复制代码
function mySqrt(x) {
  if (x < 2) return x;
  let r = x;
  while (r * r > x) {
    r = Math.floor((r + x / r) / 2); // 牛顿公式: r = (r + x/r)/2
  }
  return r;
}

时间复杂度:二分 O(log x),牛顿法接近 O(log log x)

「Q1: 为什么 right = x / 2?💥」

A1: 因为当 x ≥ 4 时,√x ≤ x/2。边界优化可减少搜索范围。

「Q2: 牛顿法会不会死循环?🤯」

A2: 不会,因为每次迭代都更接近真实值,且整数除法会收敛。但需用 Math.floor 控制精度。

「Q3: 能不能用 Math.sqrt?」

A3: 面试中通常要求手动实现。若允许,直接 Math.floor(Math.sqrt(x))

「Q4: 浮点数开方怎么做?」

A4: 扩展牛顿法,设置精度阈值(如 1e-6),直到 |r*r - x| < eps

「Q5: 大数溢出怎么处理?」

A5: 用 BigInt 或将比较改为 mid <= x / mid 避免乘法溢出。

相关推荐
passerby606130 分钟前
完成前端时间处理的另一块版图
前端·github·web components
掘了37 分钟前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅40 分钟前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅1 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax
Cobyte2 小时前
AI全栈实战:使用 Python+LangChain+Vue3 构建一个 LLM 聊天应用
前端·后端·aigc