(五)前端,如此简单!---变量

js中有三种方式可以声明变量:varletconst

可以从以下方面来区分他们。

一、作用域

  • 在函数外

    var globalVar = "我是全局变量"; // var会声明全局变量
    let letVar = "我不是window属性"; // let声明的不会声明全局变量
    const constVar = "我也不是"; // const声明的也不会

    // 全局变量自动成为window的属性
    console.log(window.globalVar); // "我是全局变量"
    console.log(window.letVar); // undefined
    console.log(window.constVar); // undefined

  • 在函数内

    function test() {
    if (true) {
    var x = 10; // 函数作用域
    let y = 20;
    const z = 30; // let/const - 块级作用域
    }
    console.log(x); // 10 - 在函数内可访问
    console.log(y); // ReferenceError: y is not defined
    console.log(z); // ReferenceError: z is not defined
    }

二、变量提升

变量提升就是JavaScript 在编译阶段就把所有变量声明记录进作用域,但赋值操作仍留在原地的一种机制。

声明"提前",赋值"不动"。

复制代码
// var a = 5;提到了前面
console.log(a); // undefined (不会报错)
var a = 5;

// let/const  编译时已知道有个变量 b,但进入 TDZ(暂时性死区),
// 在 let/const b 语句执行完之前都不能读/写。
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;

三、重新赋值

varlet 可以重新赋值,const 不可以重新赋值,但可以改属性

复制代码
var name = "Alice";
name = "Bob"; // ✅

let age = 25;
age = 26; // ✅

const PI = 3.14; //const 变量必须在声明时赋值
PI = 3.14159; // TypeError: Assignment to constant variable

const person = { name: "Alice" };
person = { name: "Bob" }; // ❌ 不能重新赋值
person.name = "Bob"; // ✅ 可以修改属性

const numbers = [1, 2, 3];
numbers = [5, 6, 7]; // ❌ 不能重新赋值
numbers.push(4); // ✅ 可以修改数组内容

// 冻结对象(浅冻结)
const obj = { name: 'Alice', info: { age: 18 } };
Object.freeze(obj);     // 第一层冻结
obj.name = 'Bob';       // 静默失败(严格模式会抛错)
obj.info.age = 20;      // ✅  freeze 只冻结浅层

四、重复声明

var可以重复声明,letconst不能

复制代码
var count = 1;
var count = 2; // ✅ 不会报错

let total = 10;
let total = 20; // ❌ SyntaxError: Identifier 'total' has already been declared

const MAX = 100;
const MAX = 200; // ❌ SyntaxError: Identifier 'MAX' has already been declared

var count = 1;
var count = 2;
console.log(count);
// 同一块作用域里多次 var 声明会被合并。等价于============ >>
var count;   // 提升后只声明一次
count = 1;   // 第一次赋值
count = 2;   // 第二次赋值
console.log(count); // 2

五、总结

  • 如果值不需要改变 用 const

    const API_URL = "https://api.example.com";
    const container = document.getElementById('container');

  • 需要重新赋值时使用 let

    let counter = 0;
    counter = 1; // 需要改变值

    for (let i = 0; i < 10; i++) {
    // 循环变量需要改变
    }

  • 容易引起错误的 var

    for (var i = 0; i < 5; i++) {
    console.log(i); // 输出 0、1、2、3、4。同步执行
    }

    for (var i = 0; i < 5; i++) { // var 是函数作用域,所有回调都引用同一个 i
    setTimeout(function() { // 循环会立即执行完毕,i 的值从 0 增加到 5
    console.log(i); // setTimeout 的回调是异步的,会在 100ms 后执行
    }, 100); // 当回调函数执行时,循环早已结束,此时的 i 已经是 5
    } // 所以输出 5个5。

    for (let i = 0; i < 5; i++) { // let 是块作用域,每次循环迭代都会创建一个新的 i 变量
    setTimeout(function() { // 这就形成了 5 个独立的闭包
    console.log(i); // 输出 0、1、2、3、4
    }, 100);
    }

    // var 通过立即执行函数来创建闭包,实现同样的效果
    for (var i=0; i<5; i++){
    function(j){ // t=0ms: 循环开始,创建5个定时器
    setTimeout(function(){ // t=0ms: 循环结束
    console.log(j); // t=100ms: 5个定时器同时触发,打印 0 1 2 3 4
    }, 100);
    }(i)
    }

六、跨js文件的变量

index.html 中有一个按钮

复制代码
<button onclick="dayin()">点击</button>

<!-- type="module" 是使用 import 的关键 -->
<script type="module" src="script.js"></script>

script.js 从 test.js 导入变量

复制代码
import { url } from './test.js'

// type="module",这个函数默认不会添加到全局 window 对象
// 需要通过 window.dayin = dayin 显式暴露给全局作用域
window.dayin = dayin;

function dayin() {
	alert(url);
}

test.js中的变量需要导出

复制代码
// export 导出 url 变量,使其他模块可以导入使用
export var url = "yang";
相关推荐
2501_941982052 小时前
企微私域:实现企业通讯工具外部群消息的自动化主动推送
java·前端·javascript
三*一2 小时前
基于 Turf.js 实现高精度多边形修整工具(模拟 ArcGIS 修整功能)
开发语言·前端·javascript·arcgis·maobox gl·turf.js
踩着两条虫2 小时前
VTJ.PRO 在线应用开发平台的工作台与后台管理视图
前端·人工智能·ai编程
踩着两条虫2 小时前
VTJ.PRO 在线应用开发平台多平台运行时(Web, H5, UniApp)
前端·低代码·ai编程
ZC1995922 小时前
Node.js npm 安装过程中 EBUSY 错误的分析与解决方案
前端·npm·node.js
升鲜宝供应链及收银系统源代码服务2 小时前
生鲜配送供应链管理系统源代码之升鲜宝社区团购商城小程序(一)
java·前端·数据库·小程序·notepad++·供应链系统源代码·多门店收银系统
ghhgy5312 小时前
Chrome、Edge浏览器显示“由贵组织管理”,删除、解决方法
前端·chrome·edge
533_2 小时前
[svg] fill-opacity、stroke-opacity与opacity
前端
九天轩辕2 小时前
Chromium 内核深度剖析:HTML 属性解析限制导致的视频静音失效问题
前端·html·音视频