《红宝书》 |原始值与引用值

原始值与引用值

ECMAScript变量包含两种类型:原始值和引用值。

yYdE6J.png

动态属性:引用值可以随时添加、修改和删除其属下和方法;原始值不行

//引用值:将创建的对象赋值给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是完全独立的。

yYd6ns.png

引用值的复制

let obj1=new Object()
let obj2=obj1 

引用值的复制实际上是复制了指针,两个变量指向的是同一个对象,及两者改变与访问的都是同一个对象。

yYd53F.png

传递参数

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操作符,适合用来判断一个变量是否为原始值。如下图,其在判断原始值类型是很有用,但是不能判断引用值类型。

yYdLAx.png

可见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
posted @ 2021-02-03 20:24  sanhuamao  阅读(114)  评论(0编辑  收藏  举报