《红宝书》 |原始值与引用值
原始值与引用值
ECMAScript变量包含两种类型:原始值和引用值。
动态属性:引用值可以随时添加、修改和删除其属下和方法;原始值不行
//引用值:将创建的对象赋值给person变量;给该对象添加了一个name属性 let person=new Object() person.name='小明'
//原始值:不能有属性 let name='小明' name.age=16 //undefined
复制值
原始值的复制
let num1=5
let num2=num1
//num2会得到5,变成了num1的副本。但num2与num1是完全独立的。
引用值的复制
let obj1=new Object()
let obj2=obj1
引用值的复制实际上是复制了指针,两个变量指向的是同一个对象,及两者改变与访问的都是同一个对象。
传递参数
ECMAScript中所有函数的参数都是按值传递的,即函数外的值会被复制到函数内部的参数中。如果是原始值,那么就跟原始值变量的复制一样,如果是引用值,就跟引用值变量的复制一样。
原始值的传递
function addTen(num){
num+=10
return num
}
let count1=10
let count2=addTen(count1)
consolo.log(count1)//10
consolo.log(count2)//20
addTen(num)
的参数num
是一个局部变量。在调用函数时,count
作为参数传入函数中,count
的值会被复制到num
中。参数num
与变量count
互不干扰。
引用值的传递
function setName(obj){
obj.name='小明'
obj=new Object()//设置成新对象
obj.name='小红'
}
let person=new Object()
setName(person)
consolo.log(person.name)//小明
同理,变量person
被复制到参数obj
中,此时变量person
与参数obj
指向的是同一个对象。所以当函数内部给obj
添加了name属性,该结果也会反映在外部变量person
身上。
而为什么结果不是小红,这是因为参数是按值传递的,其原始的引用不变。当参数obj
被设置成了新对象时,它变成了指向本地对象的指针, 该本地对象在函数执行结束时会被销毁。
确定类型
前面提到了typeof
操作符,适合用来判断一个变量是否为原始值。如下图,其在判断原始值类型是很有用,但是不能判断引用值类型。
可见typeof
不能判断引用值的类型,为解决该问题,可以使用instanceof
操作符,它可以帮助我们判断某一变量是否属于某一对象。此外,如果检测到的是原始值,会直接返回false。
//语法
result=variable instanceof constructor
//例子
console.log(person instanceof Objcet) //变量person是由Objcet对象构建的吗?
console.log(person instanceof Array) //变量person是由Array对象构建的吗?
console.log(person instanceof RegRxp) //变量person是由RegRxp构建的吗?
所有引用值都是Object实例,因此通过
instanceof
操作符检测任何引用值和Objcet构造函数都会返回true。下面例子中,Array就是一个构造函数,它是Object的实例:console.log(Array instanceof Object)//true