当前位置: 首页 > web >正文

JavaScript 中给变量赋值

在JavaScript开发中,变量赋值是一个看似简单却容易让人误解的概念。很多开发者(包括曾经的我)可能会简单地认为所有变量赋值都是"复制"过程,或者都是"引用"过程。实际上,JavaScript中的变量赋值行为取决于数据类型。本文将详细解析JavaScript中不同数据类型的赋值机制,并通过代码示例和图表帮助你彻底理解这一重要概念。

内存模型图解

为了更直观地理解这些概念,让我们用Mermaid图表展示内存中的情况:

函数参数-重新赋值
引用数据类型-修改后
引用数据类型-初始状态
基本数据类型
赋值
b++
重新赋值
1,2,3
外部arr
函数内a
3,2,1
1,2,3,4
arr
brr
1,2,3
arr
brr
b:3
a:3
b:4

基本数据类型:复制过程

对于数字、字符串、布尔值等基本数据类型,JavaScript采用的是值复制的方式。

// 数字类型示例
var a = 3;      // 声明变量a并赋值为3
var b = a;      // 将a的值复制给b
b++;            // b的值增加1
console.log(a); // 输出: 3 - a的值不受影响
console.log(b); // 输出: 4 - 只有b的值改变了// 字符串类型示例
var c = 'string';   // 声明变量c并赋值为'string'
var d = c;          // 将c的值复制给d
c += ' is String';  // 修改c的值
console.log(c);     // 输出: 'string is String' - c的值已改变
console.log(d);     // 输出: 'string' - d的值保持不变

从上面的例子可以看出,对于基本数据类型,变量赋值确实是创建了一个独立的副本,修改其中一个变量不会影响另一个变量。

引用数据类型:地址引用

对于对象(Object)和数组(Array)这样的引用数据类型,情况就不同了。JavaScript采用的是地址引用的方式。

// 数组类型示例
var arr = [1, 2, 3];   // 声明数组arr
var brr = arr;         // brr和arr引用同一个数组
brr.push(4);           // 通过brr修改数组
console.log(arr);      // 输出: [1, 2, 3, 4] - arr也被修改了
console.log(brr);      // 输出: [1, 2, 3, 4] - 两个变量指向同一个数组// 对象类型示例
var obj = {a: 1, b: 2};  // 声明对象obj
var obj2 = obj;          // obj2和obj引用同一个对象
obj.c = 3;               // 通过obj添加新属性
console.log(obj);       // 输出: {a: 1, b: 2, c: 3}
console.log(obj2);      // 输出: {a: 1, b: 2, c: 3} - 两个变量指向同一个对象

这种情况下,变量实际上存储的是对内存中对象的引用(可以理解为地址),而不是对象本身的副本。因此,通过任何一个变量修改对象,都会影响到所有引用该对象的变量。

函数参数传递的特殊情况

当引用类型作为函数参数传递时,行为会有些微妙的变化:

var arr = [1, 2, 3];  // 原始数组// 情况1:修改参数内部属性
function change(a) {a.push(4);       // 修改传入的数组return a;
}
var brr = change(arr);
console.log(arr);    // 输出: [1, 2, 3, 4] - 原数组被修改
console.log(brr);    // 输出: [1, 2, 3, 4]// 情况2:重新赋值参数
function set(a) {a = [3, 2, 1];  // 给参数赋新值,改变了引用地址return a;
}
var crr = set(arr);
console.log(arr);    // 输出: [1, 2, 3, 4] - 原数组未被修改
console.log(crr);    // 输出: [3, 2, 1] - 返回的是新数组

这里的关键区别在于:

  1. 如果只是修改参数内部的属性/元素,外部的变量会受到影响
  2. 如果对参数进行重新赋值,则外部的变量不会受到影响,因为参数现在引用的是一个新的对象

实践:

  1. 基本数据类型(Number, String, Boolean等)赋值是值复制,修改不会相互影响
  2. 引用数据类型(Object, Array等)赋值是地址引用,修改会相互影响
  3. 函数参数传递
    • 修改参数内部属性会影响外部变量
    • 重新赋值参数不会影响外部变量

在实际开发中,为了避免意外的副作用,处理引用类型时可以考虑:

// 创建数组/对象的副本
var newArr = [...oldArr];      // 数组展开运算符
var newObj = {...oldObj};      // 对象展开运算符
var deepCopy = JSON.parse(JSON.stringify(complexObj)); // 深拷贝// 函数内避免修改外部对象
function safeModify(obj) {const localObj = {...obj};  // 创建副本localObj.property = 'new value';return localObj;
}
http://www.xdnf.cn/news/13081.html

相关文章:

  • Spring Boot SQL数据库功能详解
  • SpringCloud微服务架构下的日志可观测解决方案(EFK搭建)
  • 脚本安装Doris2.10和Doris Manager
  • 2.2.3 07年T1文章精读
  • 词法分析器
  • 无人机侦测与反制技术的进展与应用
  • 从零开始了解数据采集(二十九)——什么是黑灯工厂?
  • Qt开发输入法-接Qt 相关 编译流程及交叉编译 部署所遇到的问题总结
  • Qt 窗口
  • ​ 【prompt】 “PUA” 的提示词是否好用 ?—“更好的驱动LLM能力”
  • Hilt -> Android 专属依赖注入(DI)框架
  • el-select下拉框 添加 el-checkbox 多选框
  • 期权怎么判断是不是主力合约?
  • 数字人对口型合成原理详解
  • 全视通毫米波雷达跌倒监测适用于居家、社区、机构、医院四大场景
  • 网络基础概念(网络基础)
  • Spring Boot Admin监控
  • 2025.6.9总结(利与弊)
  • MyBatis————进阶
  • 「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
  • JS - 函数防抖详解
  • React 第五十八节 Router中StaticRouterProvider的使用详解及案例
  • 如何在服务器上部署 Python Django 应用
  • 打开网页即可远程控制手机,Linux系统亦可使用
  • c++学习之路1-安装部署opencv环境c++版本用visual studio
  • C#模式匹配深度解析与最佳实践
  • day49python打卡
  • MYSQL数据库
  • LeetCode 高频 SQL 50 题(基础版)之 【高级字符串函数 / 正则表达式 / 子句】· 下
  • VSCode 使用CMake 构建 Qt 5 窗口程序