JS 变量类型
JS 变量类型分为基本类型和引用类型
基本类型:基本类型有 Undefined,String,Number,Boolean,Null;按值访问,可以直接操作保存在变量的实际值。存储方式栈存储。
基本类型在复制值的时候,会在变量对象上创建一个新的值,然后把这个值复制到新变量分配的位置上面来
引用类型:保存在内存中的对象,JS 不允许直接访问变量内存的位置,就是说不能直接操变量内存空间。存储方式是堆内存。引用类型可以添加属性和方法。
引用类型在复制值的时候,同样会将存储在变量对象中的值复制一份放到新变量的分配的空间上面,但是不同的是,这个值实际上就是一个副本发指针,这个指针指向存储子堆中的一个对象,实际上是两个变量引用的是同一个对象,改变其中一个变量,也会影响另外的一个变量。
函数的参数传递是按照值访问的
当传递的参数是基本数据类型的时候
let age = 20;
function Persion(age) {
age = ++ age;
return age;
}
Person(age); // 21
console.log(age); // 20
当传递的参数是引用类型的时候,传递的参数是一个对象的时候:
let pre = new Object();
function Person(obj) {
obj.name = 'Job';
}
Person(pre) // Job
let pre = new Object();
function Person(obj) {
obj.name = 'Job';
obj = new Object();
obj.name = 'Alean';
}
Person(pre) // Job
在这个 Person 函数内部存在的的 obj 是一个局部变量,外面的 pre 是全局的变量,因为 obj 和 pre 引用的是同一个对象,在函数内部为 obj 添加属性的时候,外面的全局对象也跟着作出类反映。
为什么 pre.name 不是 Alean?
说明函数的参数传递是值传递,当函数的内部重写 obj 的时候,这个变量引用的是一个局部对象,这个局部对象在函数执行完以后就销毁类。
函数参数 obj 传递的是对象的引用(而不是 pre 对象本身),语句 obj = new Object() 是改变局部变量 obj 的引用,以后的修改不影响对象 pre 。
函数的参数(变量引用 obj)可以看作是一个局部变量。
一个容易混淆的地方
let o = { x: 1 };
let n = o;
n.x = 3;
console.log(n, o); // {x: 3} {x: 3}
o = { x: 2 };
console.log(n, o); // {x: 3} {x: 2}
第一行将 o 指向对象 {x: 1},第二行将 n 指向 o 指向的对象,第三行改变 n 所指向的对象的属性也就相当于改变 o 指向的对象的属性,而第五行只是改变 o 的指向(o = { x: 2 }),n 的指向并没有改变(继续指向 { x: 3 })。注意,这里不是给对象赋值,是改变指向。