JS 是变量类型松散的语言,这就意味着变量仅仅是在特定时间保存特定值的一个名字而已(在其他时间可能保存的是另一种数据类型的值)。
JavaScript 中值的分类
解析器必须确定这个值是基本类型值还是引用类型值.
-
基本类型值:基本类型值表示的是简单的数据段,包括: Undefined、Null、Boolean、Number 和 String,这五种基本数据类型是按值访问的。
-
引用类型值:引用类型的值是保存在内存中的对象。JS不允许直接访问内存中位置,也就是说不能直接操作对象的内存空间。为此,引用类型的值是按引用访问的(当复制保存着对象的某个变量时,操作的是对象的引用,但在为对象添加属性时,操作的是实际的对象)。
复制变量值
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制 到为新变量分配的位置上。
当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到 为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一 个对象。
- 基本类型值
var a = 100;
var b = a; // 此时 a 和 b 是仅仅数值相同的两个不同的变量
b = 200;
console.log(a); // a 还是100
- 引用类型值
var a = new Object();
var b = a; // 此时变量 a 和变量 b 的值都为一个对象的指针,也就是说变量 a和变量 b 指向同一个对象
var b.name = "Jon";
console.log(a.name); // 输出 Jon
传递参数
ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参 数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而 引用类型值的传递,则如同引用类型变量的复制一样。
- 基本类型值
function test(num) {
num += 10;
return num;
}
var a = 10;
var result = test(a);
console.log(a); // 输出10, 因为传递给函数参数的值是变量a的副本
console.log(result); // 输出20
- 引用类型值
function setName(obj) {
// 3.为参数和变量 person 指向同一个的对象添加 name 属性
obj.name = "Nicholas";
// 4.因为函数的参数都是值传递,所以此时的 obj 保存的是一个新创建的局部对象的指针
obj = new Object();
// 5.为新创建的对象添加 name 属性
obj.name = "Greg";
// 6.函数结束,局部对象销毁
}
var person = new Object();
// 1.此时给函数参数传递的是变量 person 保存的值的副本
// 2.因为变量 person 保存的值是对象的指针,所以函数参数和变量 person 指向同一个对象
setName(person);
console.log(person.name); //"Nicholas"