JS-原始值与引用值区别
JS中的变量可以分为 原始值 和引用值两种,下面将主要针对这两种变量类型进行区分。
原始值:保存原始值的变量是按值来进行访问的
引用值:引用值是保存在内存中的对象
动态属性
let name1 = "n1";
let name2 = new String("n2");
name1.age = 22;
name2.age = 25;
console.log(name1.age);//undefined
console.log(name2.age);//25
console.log(typeof name1);//string
console.log(typeof name2);//object
- 在使用new关键字时 ,则创建了一个对象类型的实例;
- 分别给原始值以及对象(引用值)添加了一个name属性,并对其进行赋值;
- 通过得到的运行结果可以发现在引用值中,可以随时添加、修改和删除其中的属性和方法,而原始值则不能拥有属性(尽管在添加时不会报错)。
复制值
原始值和引用值的复制方式也不同,在原始值的复制中,值会直接被复制到新变量的地方
let num1 = 5;
let num2 = num1;
- 如上,原始值在复制的时候,num2中会得到num1的值,但是在复制完成之后,num2是完全独立的
let obj1 = new Object();
let obj2 = obj1;
obj1.name = "n1";
console.log(obj2.name);//n1
- 如上,引用值在进行变量赋值的时候,存储在变量中的值也会被复制到新变量的位置,此时所复制的是一个指针,该指针指向在堆内存中的对象
- 两个变量此时都指向同一个对象,因此任意一个变量对其属性进行修改,都将会在另一个变量上表现出来
传递参数
变量有按值以及按引用访问两种,而传参只有按值传递
- 在按值传参时,值会被复制到一个局部变量
- 在按引用传参时,值在内存中的位置会被保留在一个局部变量中,这也就意味着本地变量的修改会反映到函数的外部
function setName(obj){
obj.name = "n1";
obj = new Object();
obj.name = "n2";
}
let person = new Object();
setName(person);
console.log(person.name);//n1
- 首先,创建了一个对象并且把它保存在了 person 这个变量中
- 然后,这个对象被传递给了 setName 方法,并被复制到了参数 obj 中
- 在函数内部,obj 和 person 都指向了同一个对象
- 但是在函数内部的另外两行代码中,又将 obj 设置成了一个新对象,并且重新设置了 name 属性
- 如果是按引用进行的传参,那么此时name应该是n2。此时值为n1,说明函数中参数的值改变之后,原始的引用值并没有改变,当在函数内部重新写入obj时,它是一个指向本地对象的指针,而不是之前的那个。本地对象在函数执行结束后被销毁
确定类型
typeof在原始值的类型判断中很有用,但是在引用值中用处不大,因此,ECMAScript提供了instanceof操作符。
- 使用方法如下:
result = variable instanceof constructor
- 如果变量是给定的引用类型,则返回true
- 例子如下:
console.log(person instanceof Object);//变量person是Object吗?
- 由instanceof检测原始值时,则始终会返回false
[1]: Professional JavaScript for Web Developers,4th Edition,by Matt Frisbie.