JavaScript青少年简明教程:赋值语句
赋值语句(assignment statement)
JavaScript的赋值语句用于给变量、对象属性或数组元素赋值。赋值语句的基本语法是使用符号 (=) 将右侧的值(称为“源操作数”)赋给左侧的变量、属性或元素(称为“目标操作数”)。
变量赋值方面,原始(基本)数据类型的变量赋值是值的复制,而引用数据类型(对象类型)的变量赋值是引用的复制。
JavaScript的变量赋值,对于基本数据类型(如数字、字符串、布尔值等),赋操作会将值复制给变量。而对于引用数据类型(如对象、数组等),赋值操作会将引用(指向对象的内存地址)复制给变量,而不是复制对象本身。这意味着,当你修改一个引用类型的变量时,实际上是修改了引用所指向的对象。
☆对于原始类型,变量赋值是通过将一个值复制给另一个变量来完成的。这意味着当你将一个原始数据类型的变量赋值给另一个变量时,实际上是将原始值复制到了新的变量中。这两个变量是完全独立的,修改其中一个变量的值不会影响另一个变量。
例如:
let a = 5.1;
let b = a;
b = 10.2;
console.log(a); // 输出 5.1
console.log(b); // 输出 10.2
当把一个原始变量的值赋给另一个原始变量时,只是把栈中的内容复制给另一个原始变量,此时这两个变量互不影响——其实在内存中是两个地址,是互相独立的存在,当一个变量值改变时,另一个变量不会因此而发生任何变化。图解如下:
【图中的红色❌,表示5.1这个值不再被变量a引用,若一个值不再被任何变量引用,可以被垃圾回收器标记为可回收的,具体的垃圾回收时间是由JavaScript引擎决定的。】
☆对于引用数据类型,变量赋值是通过将引用复制给另一个变量来完成的。引用是指向存储在内存中的对象的地址。当你将一个引用数据类型的变量赋值给另一个变量时,实际上是将引用复制到了新的变量中,这两个变量指向同一个对象,修改其中一个变量的属性会影响另一个变量。
例如:
let obj1 = { name: 'Alice' };
let obj2 = obj1;
obj2.name = 'Bob';
console.log(obj1.name); // 输出 'Bob'
console.log(obj2.name); // 输出 'Bob'
需要注意的是,当你修改引用数据类型的属性时,实际上是修改了对象本身,而不是变量。因此,所有指向该对象的变量都会反映出这个修改。图解如下:
说明:
基本赋值:通过等号(=)将一个值赋给一个变量。例如:
let x = 5;
这个赋值语句将整数值5赋给变量x。
初学者需要注意,符号=在编程中作为赋值操作符的意义和数学中作为等号的意义不同。编程中的赋值表示将右侧的值或表达式的结果赋给左侧的变量。
多重赋值:JavaScript还支持多个变量同时赋值的方式。例如:
let a = 1, b = 2, c = 3;
这个赋值语句将分别把1、2和3赋给变量a、b和c。
复合赋值操作符:JavaScript中还支持复合赋值操作符,用于将运算结果赋给变量。例如:
let x = 10;
x += 5; // 等同于 x = x + 5;
这个赋值语句将变量x的值加上5,并将结果赋给x。
JavaScript支持多种复合赋值运算符:
x += 5; // 等同于 x = x + 5
x -= 3; // 等同于 x = x - 3
x *= 2; // 等同于 x = x * 2
x /= 4; // 等同于 x = x / 4
x %= 3; // 等同于 x = x % 3
x **= 2; // 等同于 x = x ** 2 (ES7,ECMAScript 2016)。
链式赋值:JavaScript中的赋值语句支持链式赋值。例如:
let a, b, c;
a = b = c = 10;
这个赋值语句将把值10同时赋给变量a、b和c。
需要注意的是,JavaScript是一种动态类型语言,变量的类型可以在运行时改变。因此,赋值语句可以用于改变变量的类型,例如:
let x = 5;
x = "Hello";
这个赋值语句将整数值5赋给变量x,然后将字符串"Hello"赋给同一个变量x。
JavaScript在赋值过程中可能进行隐式类型转换:
let x = "5";
let y = +x; // y 是数字 5
特别提示,学习者需要明确,JavaScript的赋值操作分为 值赋值(Value Assignment)和引用赋值(Reference Assignment)两种情况。
值赋值:当将一个简单数据类型——原始数据类型(Primitive Types)包括Number、String、Boolean、null、undefined和Symbol(在ES6中引入)——赋给一个变量时,实际上是将该值复制到变量中,而不是将变量指向原始值的内存地址。这意味着变量和原始值是完全独立的,对变量的修改不会影响原始值。例如:
let x = 5;
let y = x;
x = 10;
console.log(x); // 输出 10
console.log(y); // 输出 5
在这个例子中,将变量x赋值给变量y时,实际上是将数字5复制给y。后续对变量x的修改不会影响变量y。
引用赋值:当将一个复杂数据类型——引用类型(Reference Types),包括Object、Array、Function等——赋给一个变量时,实际上是将该值的引用复制给变量,而不是将整个值复制到变量中。这意味着变量和原始值引用的是同一个内存地址,对变量的修改也会影响原始值。例如:
let obj1 = { name: "Alice" };
let obj2 = obj1;
obj2.name = "Bob";
console.log(obj1.name); // 输出 "Bob"
console.log(obj2.name); // 输出 "Bob"
在这个例子中,将变量obj1赋值给变量obj2时,实际上是将指向对象的引用复制给obj2。后续对obj2的修改也会影响obj1,因为它们引用的是同一个对象。
需要注意的是,在引用赋值中修改对象的属性不会改变原始对象的引用,但是重新赋值一个新的对象会改变原始对象的引用。例如:
let obj1 = { name: "Alice" };
let obj2 = obj1;
obj2 = { name: "Bob" };
console.log(obj1.name); // 输出 "Alice"
console.log(obj2.name); // 输出 "Bob"
在这个例子中,重新赋值一个新的对象给obj2,不会影响obj1,因为它们引用的是不同的对象。
总结起来,JavaScript中的赋值操作是根据数据类型的不同而有所区别。
基本类型(Primitive Types,原始类型):
包括Number, String, Boolean, Undefined, Null, Symbol, BigInt;
赋值操作会创建一个新的副本(值复制);
修改一个变量不会影响另一个变量,即两个变量互不影响。
引用类型(Reference Types):
包括Object, Array, Function 等;
赋值操作复制的是引用(地址),而不是实际的数据;
修改一个变量可能会影响另一个变量,因为它们指向同一个对象,或者它们引用的是同一个对象。
基本类型(Primitive Types)赋值是值赋值(value assignment),引用类型(Reference Types)赋值是引用赋值(reference assignment)。
值赋值是复制数据的值,而引用赋值是复制数据的引用。这导致了一个重要的区别:
对于值赋值,变量和原始值是独立的,对变量的修改不会影响原始值;
而对于引用赋值,变量和原始值共享同一个内存地址,对变量的修改会影响原始值。需要注意的是,这种影响仅限于修改对象的属性,而不是重新赋值一个新的对象。如果重新赋值一个新的对象给一个变量,那么原始对象的引用将会改变。
【基本类型(Primitive Types)也有人称为简单类型,引用类型(Reference Types)也有人称为复杂类型】
这种分类和赋值行为在 JavaScript 中是非常重要的概念,理解它们有助于避免在处理数据时产生意外的副作用。