0%

原始值与引用值及确定类型

原始值和引用值

ECMAScript变量可以包含两种不同类型的数据:原始值和引用值,原始值就是最简单的数据:Undefined,Null,Boolean,Number,String,Symbol,保存原始值的变量是按值访问的,因为我们操作的就是存储在变量中的实际值。

引用值是保存在内存中的对象,JavaScript不允许直接访问内存位置,操作对象时,实际上操作的对该对象的引用,而非实际的对象本身,因此,保存引用值的变量是按引用访问的。

区别

动态属性

引用值可以随时添加,修改删除属性。

而原始值不能有属性,原始值的初始化只使用原始字面量形式,如果使用new关键字则JavaScript会创建一个Object类型的实例,

1
2
3
4
5
6
7
8
let name1="Nicholas";
let name2=new String("Matt");
name1.age=27;
name2.age=26;
console.log(name1.age);//undefined
console.log(name2.age);//26
console.log(typeof name1);//string
console.log(typeof name2);//object

复制值

通过变量把一个原始值赋值到另一个变量时,原始值会被复制得到新变量的位置。

1
2
let num1=5;
let num2=num1;

num1和num2相互独立,num2是num1的副本

当把引用值从一个变量赋值给另一个变量时,存储在变量中的值也会被复制到新变量所在位置,区别在于:这里复制的值时一个指针,它指向存储在堆内存中的对象。两个变量实际上指向同一个对象。

1
2
3
4
let obj1=new Object();
let obj2=obj1;
obj1.name="Nic";
console.log(obj2.name);//Nic

传递参数

ECMAScript中所有函数的参数都是按值传递,这意味着函数外的值会被复制到函数内部参数中,就像一个变量赋值到另一个变量一样,如果是原始值,那么就跟原始值变量的复制一样,如果是引用值就和引用值的变量复制一样。

1
2
3
4
5
6
7
8
9
function addTen(num){//count的值被复制到参数num,函数内部num+10但不会影响函数外部的原始变量count
num+=10;
return num;

}
let count=20;
let res=addTen(count);
console.log(count);//20,没有变化
console.log(res);//30

如果是对象:

1
2
3
4
5
6
7
8
function setName(obj){
obj.name="Nic"//此时多了一个obj指针指向person,将name改为Nic
obj=new Object();//又创建一个指针,指向内存其他位置
obj.name="Greg";//函数调用结束,obj被销毁
}
let person=new Object();
setName(person);
console.log(person.name);//'Nic'

typeof

typeof用来判断一个变量是否为原始类型,即判断一个变量是否为字符串,数字,布尔值或undefined的最好方式,值为对象null,那么typeof返回Object

typeof虽然对原始值很有用,但是对引用值用处不大,我们通常关心一个值是不是对象,而是想知道它是什么类型的对象。

instanceof

如果变量是给定引用类型的实例,则instanceof操作符返回true

1
console.log(person instanceof Object);//变量person是Object吗

按照定义所有引用值都是Object的实例,因此通过instanceof检测的任何引用值和Object构造函数都会返回true。如果,使用instanceof检测原始值,则始终会返回false,因为原始值不是对象。