JavaScript赋值input value失败:基本类型与引用类型的区别
本文通过JavaScript中给input赋值失败的案例,深入解析基本类型与引用类型的赋值差异。详细阐述值类型按值访问、引用类型按引用访问的机制,以及栈内存与堆内存在变量复制中的不同表现,帮助开发者避免因混淆类型导致的逻辑错误。
问题背景与尝试
在开发过程中,我遇到了一个棘手的问题。以博客园首页右侧的搜索框为例,尝试通过控制台进行操作。


现在的目标是从其他来源获取数据,并将其传递给input元素,使得页面刷新后能直接显示这些数据。
这看起来并不复杂,于是我便按照自己的理解进行了尝试。
具体代码如下:

此时,id为zzk_q的元素值应当是“测试”,即input框内应该显示“测试”。然而,实际结果却出乎意料。

为什么数值没有变化呢?这不符合预期。我反复尝试了各种方法,但代码主体基本未变,依然无法成功。这时,我突然想起以前曾遇到过类似的问题,并记得当时的解决思路(当时只是找到了方法,并未深入理解原理)。于是,我决定再次尝试,代码如下:

查看运行结果:

基本类型与引用类型的本质区别
这次终于成功了。第一次遇到这个问题时,我没有深究,成功就跳过了。但这次我开始思考:为什么会这样?这两者之间究竟有何区别?区别在哪里?我反复推敲,却始终无法理解。后来经他人指点,才得知这是值类型和引用类型的问题(……)。
随后,我去查阅相关资料,发现这些内容我之前其实看过,不禁感到汗颜。
自1997年JavaScript被标准化以来,它定义了六种基本类型。直到ES6,JS程序中任何一个值都属于以下几种类型之一。
•Undefined •Null •Boolean •Number •String •Object
不过,ES6又增加了一个基本类型:Symbol 类型。由于对此了解不多,此处不作深入讨论,待日后熟悉后再行探讨。
在JavaScript的变量中,存在两种类型的值:基本类型和引用类型的值。基本类型值(也有人称为值类型)是简单的数据段,它是按值访问的,并对其中的值进行操作。而引用类型值则是那些可能由多个值构成的对象。赋值的时候,解释器必须确定值是基本类型还是引用类型。
基本数据类型包括:Undefined、Null、Boolean、Number、String。引用类型是保存在内存中的对象,即Object,对象是方法和属性的结合体。
动态属性与变量复制机制
1.类型值的动态属性
这是一个引用类型的例子:
var person = new Object();
person.name = "foo";
console.log(person.name);//foo
delete person.name;
console.log(person.name)://undefined
在这个例子中,我们先创建了一个空对象,然后将其保存在person变量中,接着给对象添加了一个属性name,并给这个属性赋值字符串“foo”,然后输出,可以看到输出了字符串foo。随后我们将这个属性删除,输出undefined。这些说明,我们可以动态地给对象添加属性和方法,如果不销毁对象或者删除属性,它们将会一直存在。
这是一个基本类型的例子:
var name = "foo";
name.age = 22;
console.log(name.age);//undefined
在这个例子中,我们将一个字符串“foo”保存在name变量中,然后也给它添加了一个属性age,并赋值22,然后输出。像我以前想的那样,该输出22,但实际情况是undefined。
这是否可以理解为基本类型的值是不可变的,而引用类型是可以动态改变的?
2.复制变量值
和上面说的一样,基本类型是按值访问的。而引用类型呢,在JavaScript和其它语言不同,允许直接访问内存中的位置,也就是说我们不可以直接操作对象的内存空间,那怎么办呢?在操作对象时,实际上是对操作对象的引用,引用类型的值是按引用对象访问的。引用类型的存储需要内存的栈内存和堆内存共同完成,栈内存保存变量标识符和指向堆内存中该对象的指针,也可以说是该对象在堆内存的地址。
先看例子:
var num1 =5;
var num2 =num1;//5
num1+=1; //6
num2;//5
从一个变量向另一个变量复制基本类型的值,我们会在变量对象上重新创建一个新值,然后把该值复制到新变量分配的位置上。这两个值是完全独立的,对两个变量进行其他操作是互不影响的。它们应该是保存在栈内存中,如下图所示:
看一下引用类型:
var obj1 = new Object();
var obj2 = obj1;
obj1.name = "foo";
console.log(obj2.name); //foo
obj2.age = 22;
console.log(obj1.age); //22
当从一个变量向另一个变量复制引用类型的值时,也会将该值复制一份放到新的空间中。但是就跟上面说的一样,引用类型的存储要栈内存和堆内存一起完成,这个值实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上是同一个指针,也就是引用同一个对象。所以,改变其中的一个变量,另一个变量也会随之改变。如下图:

参看《JavaScript高级程序设计》。
案例复盘与总结
这样一梳理,就对一开始的问题有些明白了。开头那个错误,一开始,取到input的value(此时为空),复制给title,然后试图通过改变title来期望改变input的value。但input的value(可以看成一个变量)就是一个基本类型,复制后,它俩完全独立了,互不影响。再说成功的案例,将value拿出来,先将input(对象)复制给title,然后给title添加value属性,并赋值,此时两个指向同一个对象,改变一个,也会影响另外一个。嗯,就是这样子。
虽然很多知识从书上或其他地方看了一遍或多遍,但是等你真正遇到时感觉好奇怪。怎么会这样,然后自己去找答案。等找到或是别人指出后,才发现这个以前看见过,有些甚至自己解决过(不能说解决,只能说没有深究,没有彻底弄懂)。还有一些大学的基础都忘得七七八八了(本来就学得不好)。连栈内存和堆内存都去搜了一下。嗯,既然决定走这条路了,就好好学习吧。
最后:
Good good coding,day day up!
PS:(集合和引用类型、基本数据类型赋值不一样)一个简单的java问题 先后的赋值问题
<span style="white-space:pre"> </span>List<person> list = new ArrayList<person>();
<span style="white-space:pre"> </span>person pp = new person();
<span style="white-space:pre"> </span>list.add(pp);
<span style="white-space:pre"> </span>pp.setIvalue(12);
<span style="white-space:pre"> </span>pp.setIvalue(20);
<span style="white-space:pre"> </span>pp = null;;
<span style="white-space:pre"> </span>int b = 0;
<span style="white-space:pre"> </span>int a = b;
<span style="white-space:pre"> </span>b = 8;
<span style="white-space:pre"> </span>System.out.println(a);
<span style="white-space:pre"> </span>for (person ppp : list) {
<span style="white-space:pre"> </span>ppp.getIvalue();
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
list里面的对象加进去就改不了,但是可以修改对象里面的属性值。
简单string里面的值就改变不了
结果:
11 8888
切记:最好还是按正常来写,避免混淆
JavaScript怎么准确判断数据类型:typeof、instanceof与Object.prototype.toString
2026-11-05 17:09:21
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01
